diff --git a/.gitignore b/.gitignore index 447242e24a131f0dabb862c2545084f941c52d1a..98c4d5b0015da76cc5993555a3aa31370b4a217e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,5 @@ -covers/* -*.fb2 *.log *.swp -py/__pycache__/* -py/ziptest.py -py/fb2parse.py -py/b64decode.py -fb2toepub/* -!fb2toepub/*.zip -fb2conv/* -!fb2conv/*.zip -!fb2conv/*.gz -!fb2conv/fb2epub -!fb2conv/fb2mobi -testinfo/* -speed -.htaccess +*.pid +db.sqlite3 +.idea/* diff --git a/.project b/.project new file mode 100644 index 0000000000000000000000000000000000000000..b8a245a993f321dd8f4a8e0c78d4f47ae1c69dc5 --- /dev/null +++ b/.project @@ -0,0 +1,18 @@ + + + sopds + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + org.python.pydev.django.djangoNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000000000000000000000000000000000000..2e1d7bfd5815be2ea6db42a29e52432608d4579c --- /dev/null +++ b/.pydevproject @@ -0,0 +1,12 @@ + + + +DJANGO_MANAGE_LOCATION +manage.py + + +/${PROJECT_DIR_NAME} + +python 3.0 +Default + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000000000000000000000000000000000..c54610c4cd85c2bdcd40aa7fa424c7ce5a43b424 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//opds_catalog/dl.py=utf-8 +encoding//opds_catalog/sopdscan.py=utf-8 +encoding//opds_catalog/tests/test_dl.py=utf-8 +encoding//opds_catalog/tests/test_feeds.py=utf-8 +encoding/=UTF-8 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..951e55d42634926136ccae85daba72f9766d679b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: python +python: + - 3.3 + - 3.4 + - 3.5 + +install: + - if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then travis_retry pip install -r requirements-p33.txt; fi + - if [[ $TRAVIS_PYTHON_VERSION == '3.4' || $TRAVIS_PYTHON_VERSION == '3.5' ]]; then travis_retry pip install -r requirements.txt; fi + +script: + - python manage.py test + +branches: + only: + - v0.31-devel + diff --git a/README.md b/README.md index a2b99fb759ce399dd0a650574a75a6436455f9e3..a047ad5130db21c39cf1522e188021585c41bbea 100644 --- a/README.md +++ b/README.md @@ -1,250 +1,145 @@ -#### Simple OPDS Catalog - Простой OPDS Каталог -#### Author: Dmitry V.Shelepnev -#### Версия 0.23.4 - -#### 1. Установка Simple OPDS в Fedora, RedHat, CentOS: - -1.1 Зависимости. -Требуется Mysql не ниже версии 5 (необходима поддержка хранимых процедур) -Требуется Python не ниже версии 3.3 (используется атрибут zlib.Decompressor.eof, введенный в версии 3.3) - -Для работы проекта необходимо установить следующие зависимости: - - yum install mysql - yum install python3 - yum install mysql-connector-python3 - -1.2 Установка. -Загрузить проект можно с сайта www.sopds.ru. -Проект имеет следующую структуру: - ->opds - каталог проекта (можно задать свое имя каталога) -> py - каталог с программами на Python -> db - каталог инициализационные скрипты для создания БД -> conf - каталог с файлом конфигурации -> logs - каталог для log-файлов -> README.md - файл README - -1.3 Конфигурационный файл. -Перед началом работы необходимо внести необходимые настройки в файл конфигурации ./conf/sopds.conf -В основном необходимо при помощи параметра root_lib указать путь к Вашей коллекции книг -остальные параметры можно оставить "по умолчанию" - -1.4 Инициализация базы данных. -Во первых для работы каталога необходимо создать базу данных "sopds" и пользователя с необходимыми правами, -например следующим образом: - - mysql -uroot -proot_pass mysql - mysql > create database if not exists sopds default charset=utf8; - mysql > grant all on sopds.* to 'sopds'@'localhost' identified by 'sopds'; - mysql > commit; - mysql > ^C - -Далее в созданную базу данных необходимо загрузить структуру БД и заполненную таблицу жанров, например -следующим образом: - - mysql -usopds -psopds sopds < ./db/tables.sql - mysql -usopds -psopds sopds < ./db/genres.sql - -Все указанные выше процедуры могут быть выполнены при помощи скрипта ./db/db_create.sh суперпользователем root (для Fedora) - -1.5 Использование OPDS-сервера. -OPDS-Сервер запускается командой: - - ./sopdsd.py start - -Указанная команда запустит два процесса в режиме демона Linux: -- Демон сканирования, который будет производить периодическое сканирование Вашей коллекции книг на основании настроек в - секции [scand] конфигурационного файла -- Демон http-opds-сервера, который предоставит доступ к коллекции книг OPDS-клиентам (по умолчанию прослушивается порт 8081) - на основании настроек в секции [httpd] конфигурационного файла. Доступ к OPDS-каталогу в этом случае можно получить - по адресу http://<Ваш Сервер>:8081/ - -> Команда ./sopdsd.py stop - приведет к остановке обеих процессов -> Команда ./sopdsd.py status - покажет информацию о состоянии процессов - - Модуль sopdsd.py предоставляет все возможности пакета Simple OPDS и в большинстве случаев достаточно использовать только его. - - Для пользователей, которые по каким-то причинам желают обновлять БД SOPDS вручную в пакете присутствует - программа однократного сканирования коллекции книг: sopds-scan.py - - Для доступа к коллекции книг, при желании можно использовать внешний HTTP-сервер, такой как Apache, или Nginx для этого в - пакете программ присутсвуют скрипты: - - sopds.cgi для использования технологии CGI (смотри раздел Базовая настройка CGI в сервере Apache) - - sopds.wsgi для использования технологии WSGI (см. раздел Базовая настройка WSGI в сервере Apache) - -1.6 Обновление версий -- Поскольку при переходе от версии к версии возможно изменение структуры БД необходимо пересоздать ее следующей командой - ./db/db_create.sh либо выполнить рекомендации в п.1.4 - -1.7 Возможные проблемы: -На слабых компьютерах (в основном на NAS) может возникнуть проблема с работой MYSQL (MariaDB). -Один из запросов в хранимой процедуре sp_mark_dbl приводит к тому, что mysql создает достаточно объемный временный файл. -Если раздел, где создается временный файл (чаще всего /tmp) не очень большой, то раздел переполняется, что приводит к невозможности выполнения запроса и возникает ошибка: - -> mysql.connector.errors.DatabaseError: 3 (HY000): Error writing file '/tmp/MYdaGhaA' (Errcode: 28) - - -Пока могу предложить следующие решения: -1. Отключить обработку дубликатов (DOUBLICATES_FIND=no) -либо -2. В файле конфигурации mysql указать новый путь к tmpdir, который имеет достаточный размер. - (например в файл конфигурации для MySQL - my.cnf в раздел [msqld] записать строку tmpdir=/var/tmp - /var/tmp конечно же должен существовать, ну и перегрузить после этого mysqld) - - -#### 2. Настройка конвертации fb2 в EPUB или MOBI (опционально, можно не настраивать) - -2.1 Конвертер fb2-to-epub http://code.google.com/p/fb2-to-epub-converter/ -- во первых необходимо скачать последнюю версию конвертера fb2toepub по ссылке выше (текущая уже находится в проекте) - к сожалению конвертер не совершенный и не все книги может конвертирвать, но большинство все-таки конвертируется -- далее, необходимо скопировать архив в папку opds/fb2toepub и разархивировать -- далее, компилируем проект командой make, в результате в папке unix_dist появится исполняемый файл fb2toepub -- в конфигурационном файле sopds.conf необходимо задать путь к этому конвертеру, а также путь к временной папке, - куда будут помещаться сконвертированные файлы, например таким образом: - -> fb2toepub=../fb2toepub/unix_dist/fb2toepub -> temp_dir=/tmp - -- В результате OPDS-клиенту будут предоставлятся ссылки на FB2-книгу в формате epub - -2.2 Конвертер fb2epub http://code.google.com/p/epub-tools/ (конвертер написан на Java, так что в вашей системе должнен быть установлен как минимум JDK 1.5) -- также сначала скачать последнюю версию по ссылке выше (текущая уже находится в проекте) -- скопировать jar-файл например в каталог opds/fb2epub (Здесь уже лежит shell-скрипт для запуска jar-файла) -- Соответственно прописать пути в файле конфигурации sopds.conf к shell-скрипту fb2epub - -> fb2toepub=../fb2epub/fb2epub -> temp_dir=/tmp - -2.3 Конвертер fb2conv (конвертация в epub и mobi) http://www.the-ebook.org/forum/viewtopic.php?t=28447 -- Необходимо установить python 2.7 и пакеты lxml, cssutils: - - yum install python - yum install python-lxml - yum install python-cssutils - -- скачать последнюю версию конвертера по ссылке выше (текущая уже находится в каталоге fb2conv проекта) -- скачать утилиту KindleGen с сайта Amazon http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000234621 - (текущая версия утилиты уже находится в каталоге fb2conv проекта) -- скопировать архив проекта в opds/fb2conv (Здесь уже подготовлены shell-скрипты для запуска конвертера) и разархивировать его -- Для конвертации в MOBI нужно архив с утилитой KindleGen положить в каталог с конвертером и разархивировать -- В конфигурационном файле sopds.conf задать пути к соответствующим скриптам: - -> fb2toepub=../fb2conv/fb2epub -> fb2tomobi=../fb2conv/fb2mobi -> temp_dir=/tmp - - -#### 3. Базовая настройка CGI в сервере Apache -- Для работы CGI-скрипта необходимо разрешить доступ к каталогу opds/py, например при помощи следующих директив конфигурационного - файла web-сервера Apache httpd.conf: - - - Options Indexes FollowSymLinks - AllowOverride All - Order allow,deny - Allow from all - - Alias /opds "/home/www/opds/py" - Alias /web "/home/www/opds/py" - -- Далее, необходимо разрешить запуск cgi-скрипта ./py/sopds.cgi - при помощи директив, помещенных в файл .htaccess, который необходимо создать в корне пакета SOPDS - (например: /home/www/opds/.htaccess) - - Options ExecCGI - AddHandler cgi-script .cgi - -- Для настройки аутентификации, создайте пользователя командой: - - htpasswd -c /home/www/opds/.htpasswd user - - и добавьте в .htaccess следующие строки: - - AuthType Basic - AuthName "SOPDS Library" - AuthUserFile /home/www/opds/.htpasswd - require valid-user - -- при выполнении указанных выше процедур доступ к OPDS-каталогу можно получить по следующим адресам (opds и web формат): - -> http://<Ваш Сервер>/opds/sopds.cgi -> http://<Ваш Сервер>/web/sopds.cgi - -- для сокращения URL доступа добавьте следующую директиву в файл .htaccess: - - DirectoryIndex index.xml sopds.cgi - - при использовании указанной директивы доступ к OPDS-каталогу можно получить по следующим адресам: - -> http://<Ваш Сервер>/opds/ -> http://<Ваш Сервер>/web/ - - -- для некоторых систем (например Ubuntu 12.04) возможно понадобится включить "CGI processing in Apache" командой: - - sudo a2enmod cgi - - -#### 4. Базовая настройка WSGI в сервере Apache -WSGI - Web Server Gateway Interface - более эффективный стандарт взаимодействия Python программ с Веб сервером, чем CGI -WSGI в отличие от CGI позволяет не загружать интерпертатор Python со скриптом каждый раз, когда происходит обращение к -CGI-скрипту. Вместо этого Python-программа загружается однократно и выполняется при помощи постоянно загруженного модуля -mod_wsgi. - -4.1 Установка mod_wsgi -- Для работы WSGI скрипта необходимо загрузить, скомпилировать и установить модуль mod_wsgi для Apache. Ньюанс тут только в том, - что нужный нам mod_wsgi должен быть скомпилирован для python3. Таких, уже готовых модулей я для своей системы не нашел, поэтому - пришлось выполнить несложные шаги для компиляции нужного нам модуля: - - yum install hg # Устанавливаем клинета для Mercurial на которой ведется разработка mod_wsgi - hg clone https://code.google.com/p/modwsgi/ # Скачиваем исходники mod_wsgi - cd ./modwsgi/mod_wsgi - ./configure --with-python=/usr/bin/python3.3 # Конфигурим под наш Python3 - make # Компилируем - make install # Устанавливаем - -- Прописываем в конфигурационный файл нашего сервера Apache следующую строку (Возможно она уже там есть) - - LoadModule wsgi_module modules/mod_wsgi.so - -4.2 Настройка разрешений на запуск wsgi-скрипта делается аналогично настройке для CGI скрипта, т.е необходимо разрешить доступ к каталогу opds/py и -добавить в файл .htaccess, следующие строки: - - Options ExecCGI - AddHandler wsgi-script .wsgi - -- при выполнении указанных выше процедур доступ к OPDS-каталогу можно получить по следующим адресам (opds и web формат): - -> http://<Ваш Сервер>/opds/sopds.wsgi -> http://<Ваш Сервер>/web/sopds.wsgi - -- для сокращения URL доступа добавьте следующую директиву в файл .htaccess: - - DirectoryIndex index.xml sopds.wsgi - - при использовании указанной директивы доступ к OPDS-каталогу можно получить по следующим адресам: - -> http://<Ваш Сервер>/opds/ -> http://<Ваш Сервер>/web/ - -4.3 Возможные проблемы. -- Одна из выявленных мной проблем совместимости скрипта sopds.wsgi с веб-сервером Apache состоит в том, что и SOPDS и Apache -используют библиотеку "libexpat". И если версия libexpat, загруженная сервером Apache сильно отличается от той, которую -нужна Питону, то происходит crash приложения sopds.wsgi. -Подробное описание этой проблемы и возможных путей решений находится здесь: - -> https://code.google.com/p/modwsgi/wiki/IssuesWithExpatLibrary - - Что в итоге сделал я: - Удалил сиволические ссылки на старую библиотеку libexpat из каталога модулей сервера Apache: - - unlink /usr/local/apache2/lib/libexpat.so - unlink /usr/local/apache2/lib/libexpat.so.0 - - А затем создал новые на ту библиотеку, которая используется Питоном: - - ln -s /usr/lib/libexpat.so.1.6.0 /usr/local/apache2/lib/libexpat.so - ln -s /usr/lib/libexpat.so.1.6.0 /usr/local/apache2/lib/libexpat.so.0 - - Ну и перезагрузил Apache. - +#### Simple OPDS Catalog - Простой OPDS Каталог +#### Author: Dmitry V.Shelepnev +#### Версия 0.33 beta + +#### 1. Простая установка Simple OPDS (используем простую БД sqlite3) + +1.1 Зависимости. +- Требуется Python не ниже версии 3.3 (используется атрибут zlib.Decompressor.eof, введенный в версии 3.3) +- Django 1.8 +- Pillow 2.9.0 +- apscheduler 3.3.0 + +Для работы проекта необходимо установить указанные зависимости: + + yum install python3 + pip install -r requirements.txt + +1.2 Установка проекта +Загрузить архив с проектом можно с сайта www.sopds.ru, +либо из github.com следующей командой: + + git clone git@github.com:mitshel/sopds.git + +1.3 Настраиваем ./sopds/settings.py (настройки в конце файла) + + SOPDS_ROOT_LIB = < Путь к каталогу с книгами > + SOPDS_AUTH = < False | True > + SOPDS_SCAN_SHED_MIN = '0,12' + SOPDS_SCAN_SHED_HOUR = '0' + +1.4 Производим инициализацию базы данных и заполнение начальными данными (жанры) + + python3 manage.py migrate + python3 manage.py sopds_util --clear + +1.5 Cоздаем суперпользователя + + python3 manage.py createsuperuser + +1.6 Вручную запускаем разовое сканирование коллекции книг (Выполняется очень долго) + + python3 manage.py sopds_scanner scan --daemon + +1.7 Запускаем встроенный HTTP/OPDS сервер + + python3 manage.py sopds_server start --daemon + +Однако наилучшим способом, все же является настройка в качестве HTTP/OPDS серверов Apache или Nginx +(точка входа ./sopds/wsgi.py) + +1.8 Запускаем SCANNER сервер (опционально, необходим для автоматизированного периодического пересканирования коллекции) +Перед запуском SCANNER сервера необходимо убедится, что сканирование, запущеное в п.1.6 уже завершено, +т.к. может возникнуть ситуация с запуском параллельного процесса сканирования, что может привести к ошибкам. +Примите во внимание, что в настройках, указанных в п.1.3 задан периодический запуск сканирования 2 раза +в день 12:00 и 0:00. + + python3 manage.py sopds_scanner start --daemon + +1.9 Доступ к информации +Если все предыдущие шаги выполнены успешно, то к библиотеке можно получить доступ по следующим URL: +> OPDS-версия: http://<Ваш сервер>:8001/opds/ +> HTTP-версия: http://<Ваш сервер>:8001/ + +Следует принять во внимание, что по умолчанию в проекте используется простая БД sqlite3, которая +является одно-пользовательской. Поэтому пока не будет завершен процесс сканирования, запущенный +ранее пунктом 1.6 попытки доступа к серверу будут завершаться ошибкой +"A server error occurred. Please contact the administrator." +Для устранения указанной проблемы необходимо ипользовать многопользовательские БД, Например MYSQL. + +#### 2. Настройка базы данных MySQL (опционально, но очень желательно для увеличения производительности). +2.1 Для работы с большим количеством книг, очень желательно не использовать sqlite, а настроить для работы БД MySQL. +MySQL по сравнению с sqlite работает гораздо быстрее, например скорость сканирования книг при использованиии MySQL +увеличится приблизительно в ПЯТЬ!!! раз. +Для этого необходимо сначала в БД MySQL создать базу данных "sopds" и пользователя с необходимыми правами, +например следующим образом: + + mysql -uroot -proot_pass mysql + mysql > create database if not exists sopds default charset=utf8; + mysql > grant all on sopds.* to 'sopds'@'localhost' identified by 'sopds'; + mysql > commit; + mysql > ^C + +2.2 Далее в конфигурационном файде нужно закомментировать строки подключения к БД sqlite и соответсвенно раскомментировать +строки подключения к БД Mysql: + + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'sopds', + 'HOST': 'localhost', + 'USER': 'sopds', + 'PASSWORD' : 'sopds' + } + } + + # DATABASES = { + # 'default': { + # 'ENGINE': 'django.db.backends.sqlite3', + # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + # } + #} + +2.4 Далее необходимо для инициализации и заполнения вновь созданной БД заново выполнить пункты 1.4 - 1.9 данной инструкции +Однако, если Вы уже ранее запустили HTTP/OPDS сервер и SCANNER сервер, то потребуется сначала остановить их: + + python3 manage.py sopds_server stop + python3 manage.py sopds_scanner stop + +#### 3. Настройка конвертации fb2 в EPUB или MOBI (опционально, можно не настраивать) + +3.1 Конвертер fb2-to-epub http://code.google.com/p/fb2-to-epub-converter/ +- во первых необходимо скачать последнюю версию конвертера fb2toepub по ссылке выше (текущая уже находится в проекте) + к сожалению конвертер не совершенный и не все книги может конвертировать, но большинство все-таки конвертируется +- далее, необходимо скопировать архив в папку **./convert/fb2toepub** и разархивировать +- далее, компилируем проект командой make, в результате в папке unix_dist появится исполняемый файл fb2toepub +- в конфигурационном файле ./sopds/settings.py необходимо задать путь к этому конвертеру, например таким образом: + +> SOPDS_FB2TOEPUB = os.path.join(BASE_DIR,'convert/fb2toepub/unix_dist/fb2toepub') + +- В результате OPDS-клиенту будут предоставлятся ссылки на FB2-книгу в формате epub + +3.2 Конвертер fb2epub http://code.google.com/p/epub-tools/ (конвертер написан на Java, так что в вашей системе должнен быть установлен как минимум JDK 1.5) +- также сначала скачать последнюю версию по ссылке выше (текущая уже находится в проекте) +- скопировать jar-файл например в каталог **./convert/fb2epub** (Здесь уже лежит shell-скрипт для запуска jar-файла) +- Соответственно прописать пути в файле конфигурации **./sopds/settings.py** к shell-скрипту fb2epub (данный конвертер работает также и в Windows) + +> SOPDS_FB2TOEPUB = os.path.join(BASE_DIR, 'convert\\fb2epub\\fb2epub.cmd' if sys.platform =='win32' else 'convert/fb2epub/fb2epub' ) + +3.3 Конвертер fb2conv (конвертация в epub и mobi) http://www.the-ebook.org/forum/viewtopic.php?t=28447 +- Необходимо установить python 2.7 и пакеты lxml, cssutils: + + yum install python + yum install python-lxml + yum install python-cssutils + +- скачать последнюю версию конвертера по ссылке выше (текущая уже находится в каталоге fb2conv проекта) +- скачать утилиту KindleGen с сайта Amazon http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000234621 + (текущая версия утилиты уже находится в каталоге fb2conv проекта) +- скопировать архив проекта в **./convert/fb2conv** (Здесь уже подготовлены shell-скрипты для запуска конвертера) и разархивировать его +- Для конвертации в MOBI нужно архив с утилитой KindleGen положить в каталог с конвертером и разархивировать +- В конфигурационном файле **./sopds/settings.py** задать пути к соответствующим скриптам: + +> SOPDS_FB2TOEPUB = os.path.join(BASE_DIR,'convert/fb2conv/fb2epub') +> SOPDS_FB2TOMOBI = os.path.join(BASE_DIR,'convert/fb2conv/fb2mobi') + diff --git a/assets/sopds-sass/.bowerrc b/assets/sopds-sass/.bowerrc new file mode 100644 index 0000000000000000000000000000000000000000..69fad358018d530235f8e43c483d3ce960616a32 --- /dev/null +++ b/assets/sopds-sass/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "bower_components" +} diff --git a/assets/sopds-sass/.gitignore b/assets/sopds-sass/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..1cc7e84ac7955b6083c92691d8a39041e2061111 --- /dev/null +++ b/assets/sopds-sass/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +bower_components +node_modules +npm-debug.log +css diff --git a/assets/sopds-sass/CHANGELOG.md b/assets/sopds-sass/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..381e1a1add9019874cfea3abb08ff1e42c1afc63 --- /dev/null +++ b/assets/sopds-sass/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## Version 1.0 (November 19, 2015) + +Initial release. diff --git a/assets/sopds-sass/README.md b/assets/sopds-sass/README.md new file mode 100644 index 0000000000000000000000000000000000000000..36ca655393662fd27292f1ca82620c17e6c9bf3d --- /dev/null +++ b/assets/sopds-sass/README.md @@ -0,0 +1,48 @@ +# Foundation for Sites Template + +**Please open all issues with this template on the main [Foundation for Sites](https://github.com/zurb/foundation-sites/issues) repo.** + +This is the basic starter project for [Foundation for Sites 6](http://foundation.zurb.com/sites). It includes a Sass compiler and a starter HTML file for you. + +## Installation + +To use this template, your computer needs: + +- [NodeJS](https://nodejs.org/en/) (0.12 or greater) +- [Git](https://git-scm.com/) + +This template can be installed with the Foundation CLI, or downloaded and set up manually. + +### Using the CLI + +Install the Foundation CLI with this command: + +```bash +npm install foundation-cli --global +``` + +Use this command to set up a blank Foundation for Sites project with this template: + +```bash +foundation new --framework sites --template basic +``` + +The CLI will prompt you to give your project a name. The template will be downloaded into a folder with this name. + +### Manual Setup + +To manually set up the template, first download it with Git: + +```bash +git clone https://github.com/zurb/foundation-sites-template projectname +``` + +Then open the folder in your command line, and install the needed dependencies: + +```bash +cd projectname +npm install +bower install +``` + +Finally, run `npm start` to run the Sass compiler. It will re-run every time you save a Sass file. diff --git a/assets/sopds-sass/bower.json b/assets/sopds-sass/bower.json new file mode 100644 index 0000000000000000000000000000000000000000..2694808affea2a1fea104c91e36c0d94c18a9974 --- /dev/null +++ b/assets/sopds-sass/bower.json @@ -0,0 +1,25 @@ +{ + "name": "foundation-sites-template", + "version": "1.0.0", + "authors": [ + "ZURB " + ], + "description": "Basic template for a new Foundation for Sites project.", + "main": "index.html", + "license": "MIT", + "homepage": "http://foundation.zurb.com", + "dependencies": { + "foundation-sites": "~6.1.2", + "motion-ui": "~1.1.0", + "foundation-sites": "~6.2.0", + "motion-ui": "~1.2.2" + }, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "private": true +} diff --git a/assets/sopds-sass/gulpfile.js b/assets/sopds-sass/gulpfile.js new file mode 100644 index 0000000000000000000000000000000000000000..2a7c06be1c1e7c21bfea7c4afc58ec25491fb2f1 --- /dev/null +++ b/assets/sopds-sass/gulpfile.js @@ -0,0 +1,24 @@ +var gulp = require('gulp'); +var $ = require('gulp-load-plugins')(); + +var sassPaths = [ + 'bower_components/foundation-sites/scss', + 'bower_components/motion-ui/src' +]; + +gulp.task('sass', function() { + return gulp.src('scss/sopds.scss') + .pipe($.sass({ + includePaths: sassPaths, + outputStyle: 'compressed' // if css compressed **file size** + }) + .on('error', $.sass.logError)) + .pipe($.autoprefixer({ + browsers: ['last 2 versions', 'ie >= 9'] + })) + .pipe(gulp.dest('../../sopds_web_backend/static/css')); +}); + +gulp.task('default', ['sass'], function() { + gulp.watch(['scss/**/*.scss'], ['sass']); +}); diff --git a/assets/sopds-sass/index.html b/assets/sopds-sass/index.html new file mode 100644 index 0000000000000000000000000000000000000000..07a6fff0193fbcaae8d1b8c5f9abc141df0f1cb6 --- /dev/null +++ b/assets/sopds-sass/index.html @@ -0,0 +1,168 @@ + + + + + + + Foundation for Sites + + + +
+
+

Welcome to Foundation

+
+
+ +
+
+
+

We’re stoked you want to try Foundation!

+

To get going, this file (index.html) includes some basic styles you can modify, play around with, or totally destroy to get going.

+

Once you've exhausted the fun in this document, you should check out:

+
+
+

Foundation Documentation
Everything you need to know about using the framework.

+
+
+

Foundation Code Skills
These online courses offer you a chance to better understand how Foundation works and how you can master it to create awesome projects.

+
+
+

Foundation Forum
Join the Foundation community to ask a question or show off your knowlege.

+
+
+
+
+

Foundation on Github
Latest code, issue reports, feature requests and more.

+
+
+

@zurbfoundation
Ping us on Twitter if you have questions. When you build something with this we'd love to see it (and send you a totally boss sticker).

+
+
+
+
+
+ +
+
+
Here’s your basic grid:
+ + +
+
+
+

This is a twelve column section in a row. Each of these includes a div.callout element so you can see where the columns are - it's not required at all for the grid.

+
+
+
+
+
+
+

Six columns

+
+
+
+
+

Six columns

+
+
+
+
+
+
+

Four columns

+
+
+
+
+

Four columns

+
+
+
+
+

Four columns

+
+
+
+ +
+ +
We bet you’ll need a form somewhere:
+
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ +
+ + .com +
+
+
+
+
+
+ + +
+
+
+
+ + + +
+
+ + + +
+
+
+
+ + +
+
+
+
+ +
+
Try one of these buttons:
+

Simple Button
+ Success Btn
+ Alert Btn
+ Secondary Btn

+
+
So many components, girl!
+

A whole kitchen sink of goodies comes with Foundation. Check out the docs to see them all, along with details on making them your own.

+ Go to Foundation Docs +
+
+
+ + + + + + + diff --git a/assets/sopds-sass/js/app.js b/assets/sopds-sass/js/app.js new file mode 100644 index 0000000000000000000000000000000000000000..947ba5a441d8e9b96ad6b0bfb5f60fcf74029cfa --- /dev/null +++ b/assets/sopds-sass/js/app.js @@ -0,0 +1 @@ +$(document).foundation(); diff --git a/assets/sopds-sass/package.json b/assets/sopds-sass/package.json new file mode 100644 index 0000000000000000000000000000000000000000..01ae6399b7f251e65fb08ce198271e9b0ce62a6a --- /dev/null +++ b/assets/sopds-sass/package.json @@ -0,0 +1,30 @@ +{ + "name": "foundation-sites-template", + "version": "1.0.0", + "description": "Basic template for a new Foundation for Sites project.", + "main": "gulpfile.js", + "devDependencies": { + "gulp": "^3.9.0", + "gulp-autoprefixer": "^3.1.1", + "gulp-load-plugins": "^1.2.4", + "gulp-sass": "^2.3.2" + }, + "scripts": { + "start": "gulp", + "build": "gulp sass" + }, + "repository": { + "type": "git", + "url": "https://github.com/zurb/foundation-sites-template.git" + }, + "bugs": { + "url": "https://github.com/zurb/foundation-sites/issues", + "email": "foundation@zurb.com" + }, + "author": "ZURB ", + "license": "MIT", + "private": true, + "dependencies": { + "gulp-autoprefixer": "^3.1.0" + } +} diff --git a/assets/sopds-sass/scss/_settings.scss b/assets/sopds-sass/scss/_settings.scss new file mode 100644 index 0000000000000000000000000000000000000000..330fcb067f60616d21ab994b292184482775e627 --- /dev/null +++ b/assets/sopds-sass/scss/_settings.scss @@ -0,0 +1,584 @@ +// Foundation for Sites Settings +// ----------------------------- +// +// Table of Contents: +// +// 1. Global +// 2. Breakpoints +// 3. The Grid +// 4. Base Typography +// 5. Typography Helpers +// 6. Abide +// 7. Accordion +// 8. Accordion Menu +// 9. Badge +// 10. Breadcrumbs +// 11. Button +// 12. Button Group +// 13. Callout +// 14. Close Button +// 15. Drilldown +// 16. Dropdown +// 17. Dropdown Menu +// 18. Flex Video +// 19. Forms +// 20. Label +// 21. Media Object +// 22. Menu +// 23. Meter +// 24. Off-canvas +// 25. Orbit +// 26. Pagination +// 27. Progress Bar +// 28. Reveal +// 29. Slider +// 30. Switch +// 31. Table +// 32. Tabs +// 33. Thumbnail +// 34. Title Bar +// 35. Tooltip +// 36. Top Bar + +@import 'util/util'; + +// 0. SOPDS Constants +$sopds-bg-color: #f15a23; +$sopds-bg-hover: scale-color($sopds-bg-color, $lightness: -15%); +$sopds-topbar-bg-color: #ffffff; +$sopds-title-color: #f15a23; +$sopds-hover-color: scale-color($sopds-title-color, $lightness: -40%); + +$sopds-menu-bg-color: #f15a23; +$sopds-menu-color: #FFFFFF; +$sopds-menu-bg-hover-color: scale-color($sopds-menu-bg-color, $lightness: -15%); +$sopds-menu-bg-active-color: scale-color($sopds-menu-bg-color, $lightness: -20%); +$sopds-menu-hover-color: scale-color($sopds-menu-color, $lightness: -15%); + +// 1. Global +// --------- + +$global-font-size: 100%; +$global-width: rem-calc(1200); +$global-lineheight: 1.5; +$foundation-palette: ( +// primary: #2199e8, + primary: $sopds-bg-color, + secondary: #777, + success: #3adb76, + warning: #ffae00, + alert: #ec5840, +); +$light-gray: #e6e6e6; +$medium-gray: #cacaca; +$dark-gray: #8a8a8a; +$black: #0a0a0a; +$white: #fefefe; +$body-background: $white; +$body-font-color: $black; +$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; +$body-antialiased: true; +$global-margin: 1rem; +$global-padding: 1rem; +$global-weight-normal: normal; +$global-weight-bold: bold; +$global-radius: 0; +$global-text-direction: ltr; +$global-flexbox: false; +$print-transparent-backgrounds: true; + +@include add-foundation-colors; + +// 2. Breakpoints +// -------------- + +$breakpoints: ( + small: 0, + medium: 640px, + large: 1024px, + xlarge: 1200px, + xxlarge: 1440px, +); +$breakpoint-classes: (small medium large); + +// 3. The Grid +// ----------- + +$grid-row-width: $global-width; +$grid-column-count: 12; +$grid-column-gutter: ( + small: 20px, + medium: 30px, +); +$grid-column-align-edge: true; +$block-grid-max: 8; + +// 4. Base Typography +// ------------------ + +$header-font-family: $body-font-family; +$header-font-weight: $global-weight-normal; +$header-font-style: normal; +$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace; +$header-sizes: ( + small: ( + 'h1': 24, + 'h2': 20, + 'h3': 19, + 'h4': 18, + 'h5': 17, + 'h6': 16, + ), + medium: ( + 'h1': 48, + 'h2': 40, + 'h3': 31, + 'h4': 25, + 'h5': 20, + 'h6': 16, + ), +); +$header-color: inherit; +$header-lineheight: 1.4; +$header-margin-bottom: 0.5rem; +$header-text-rendering: optimizeLegibility; +$small-font-size: 80%; +$header-small-font-color: $medium-gray; +$paragraph-lineheight: 1.6; +$paragraph-margin-bottom: 1rem; +$paragraph-text-rendering: optimizeLegibility; +$code-color: $black; +$code-font-family: $font-family-monospace; +$code-font-weight: $global-weight-normal; +$code-background: $light-gray; +$code-border: 1px solid $medium-gray; +$code-padding: rem-calc(2 5 1); +$anchor-color: $primary-color; +$anchor-color-hover: scale-color($anchor-color, $lightness: -14%); +$anchor-text-decoration: none; +$anchor-text-decoration-hover: none; +$hr-width: $global-width; +$hr-border: 1px solid $medium-gray; +$hr-margin: rem-calc(20) auto; +$list-lineheight: $paragraph-lineheight; +$list-margin-bottom: $paragraph-margin-bottom; +$list-style-type: disc; +$list-style-position: outside; +$list-side-margin: 1.25rem; +$list-nested-side-margin: 1.25rem; +$defnlist-margin-bottom: 1rem; +$defnlist-term-weight: $global-weight-bold; +$defnlist-term-margin-bottom: 0.3rem; +$blockquote-color: $dark-gray; +$blockquote-padding: rem-calc(9 20 0 19); +$blockquote-border: 1px solid $medium-gray; +$cite-font-size: rem-calc(13); +$cite-color: $dark-gray; +$keystroke-font: $font-family-monospace; +$keystroke-color: $black; +$keystroke-background: $light-gray; +$keystroke-padding: rem-calc(2 4 0); +$keystroke-radius: $global-radius; +$abbr-underline: 1px dotted $black; + +// 5. Typography Helpers +// --------------------- + +$lead-font-size: $global-font-size * 1.25; +$lead-lineheight: 1.6; +$subheader-lineheight: 1.4; +$subheader-color: $dark-gray; +$subheader-font-weight: $global-weight-normal; +$subheader-margin-top: 0.2rem; +$subheader-margin-bottom: 0.5rem; +$stat-font-size: 2.5rem; + +// 6. Abide +// -------- + +$abide-inputs: true; +$abide-labels: true; +$input-background-invalid: map-get($foundation-palette, alert); +$form-label-color-invalid: map-get($foundation-palette, alert); +$input-error-color: map-get($foundation-palette, alert); +$input-error-font-size: rem-calc(12); +$input-error-font-weight: $global-weight-bold; + +// 7. Accordion +// ------------ + +$accordion-background: $white; +$accordion-plusminus: true; +$accordion-item-color: foreground($accordion-background, $primary-color); +$accordion-item-background-hover: $light-gray; +$accordion-item-padding: 1.25rem 1rem; +$accordion-content-background: $white; +$accordion-content-border: 1px solid $light-gray; +$accordion-content-color: foreground($accordion-background, $primary-color); +$accordion-content-padding: 1rem; + +// 8. Accordion Menu +// ----------------- + +$accordionmenu-arrows: true; +$accordionmenu-arrow-color: $primary-color; + +// 9. Badge +// -------- + +$badge-background: $primary-color; +$badge-color: foreground($badge-background); +$badge-padding: 0.3em; +$badge-minwidth: 2.1em; +$badge-font-size: 0.6rem; + +// 10. Breadcrumbs +// --------------- + +$breadcrumbs-margin: 0 0 $global-margin 0; +$breadcrumbs-item-font-size: rem-calc(11); +$breadcrumbs-item-color: $primary-color; +$breadcrumbs-item-color-current: $black; +$breadcrumbs-item-color-disabled: $medium-gray; +$breadcrumbs-item-margin: 0.75rem; +$breadcrumbs-item-uppercase: true; +$breadcrumbs-item-slash: true; + +// 11. Button +// ---------- + +$button-padding: 0.85em 1em; +$button-margin: 0 0 $global-margin 0; +$button-fill: solid; +$button-background: $primary-color; +$button-background-hover: scale-color($button-background, $lightness: -15%); +$button-color: $white; +$button-color-alt: $black; +$button-radius: $global-radius; +$button-sizes: ( + tiny: 0.6rem, + small: 0.75rem, + default: 0.9rem, + large: 1.25rem, +); +$button-opacity-disabled: 0.25; + +// 12. Button Group +// ---------------- + +$buttongroup-margin: 1rem; +$buttongroup-spacing: 1px; +$buttongroup-child-selector: '.button'; +$buttongroup-expand-max: 6; + +// 13. Callout +// ----------- + +$callout-background: $white; +$callout-background-fade: 85%; +$callout-border: 1px solid rgba($black, 0.25); +$callout-margin: 0 0 1rem 0; +$callout-padding: 1rem; +$callout-font-color: $body-font-color; +$callout-font-color-alt: $body-background; +$callout-radius: $global-radius; +$callout-link-tint: 30%; + +// 14. Close Button +// ---------------- + +$closebutton-position: right top; +$closebutton-offset-horizontal: 1rem; +$closebutton-offset-vertical: 0.5rem; +$closebutton-size: 2em; +$closebutton-lineheight: 1; +$closebutton-color: $dark-gray; +$closebutton-color-hover: $black; + +// 15. Drilldown +// ------------- + +$drilldown-transition: transform 0.15s linear; +$drilldown-arrows: true; +$drilldown-arrow-color: $primary-color; +$drilldown-background: $white; + +// 16. Dropdown +// ------------ + +$dropdown-padding: 1rem; +$dropdown-border: 1px solid $medium-gray; +$dropdown-font-size: 1rem; +$dropdown-width: 300px; +$dropdown-radius: $global-radius; +$dropdown-sizes: ( + tiny: 100px, + small: 200px, + large: 400px, +); + +// 17. Dropdown Menu +// ----------------- + +//$dropdownmenu-arrows: true; +$dropdownmenu-arrows: false; +$dropdownmenu-arrow-color: $anchor-color; +$dropdownmenu-min-width: 200px; +$dropdownmenu-background: $white; +$dropdownmenu-border: 1px solid $medium-gray; + +// 18. Flex Video +// -------------- + +$flexvideo-margin-bottom: rem-calc(16); +$flexvideo-ratio: 4 by 3; +$flexvideo-ratio-widescreen: 16 by 9; + +// 19. Forms +// --------- + +$fieldset-border: 1px solid $medium-gray; +$fieldset-padding: rem-calc(20); +$fieldset-margin: rem-calc(18 0); +$legend-padding: rem-calc(0 3); +$form-spacing: rem-calc(16); +$helptext-color: $black; +$helptext-font-size: rem-calc(13); +$helptext-font-style: italic; +$input-prefix-color: $black; +$input-prefix-background: $light-gray; +$input-prefix-border: 1px solid $medium-gray; +$input-prefix-padding: 1rem; +$form-label-color: $black; +$form-label-font-size: rem-calc(14); +$form-label-font-weight: $global-weight-normal; +$form-label-line-height: 1.8; +$select-background: $white; +$select-triangle-color: $dark-gray; +$select-radius: $global-radius; +$input-color: $black; +$input-placeholder-color: $medium-gray; +$input-font-family: inherit; +$input-font-size: rem-calc(16); +$input-background: $white; +$input-background-focus: $white; +$input-background-disabled: $light-gray; +$input-border: 1px solid $medium-gray; +$input-border-focus: 1px solid $dark-gray; +$input-shadow: inset 0 1px 2px rgba($black, 0.1); +$input-shadow-focus: 0 0 5px $medium-gray; +$input-cursor-disabled: default; +$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out; +$input-number-spinners: true; +$input-radius: $global-radius; + +// 20. Label +// --------- + +$label-background: $primary-color; +$label-color: foreground($label-background); +$label-font-size: 0.8rem; +$label-padding: 0.2rem 0.2rem; +$label-radius: $global-radius; + +// 21. Media Object +// ---------------- + +$mediaobject-margin-bottom: $global-margin; +$mediaobject-section-padding: $global-padding; +$mediaobject-image-width-stacked: 100%; + +// 22. Menu +// -------- + +$menu-margin: 0; +$menu-margin-nested: 1rem; +$menu-item-padding: 0.5rem 0.5rem; +//$menu-item-padding: 0.25rem 1rem; +$menu-item-color-active: $white; +//$menu-item-background-active: map-get($foundation-palette, primary); +$menu-item-background-active: $sopds-menu-bg-active-color; +$menu-icon-spacing: 0.25rem; + +// 23. Meter +// --------- + +$meter-height: 1rem; +$meter-radius: $global-radius; +$meter-background: $medium-gray; +$meter-fill-good: $success-color; +$meter-fill-medium: $warning-color; +$meter-fill-bad: $alert-color; + +// 24. Off-canvas +// -------------- + +$offcanvas-size: 250px; +$offcanvas-background: $light-gray; +$offcanvas-zindex: -1; +$offcanvas-transition-length: 0.5s; +$offcanvas-transition-timing: ease; +$offcanvas-fixed-reveal: true; +$offcanvas-exit-background: rgba($white, 0.25); +$maincontent-class: 'off-canvas-content'; +$maincontent-shadow: 0 0 10px rgba($black, 0.5); + +// 25. Orbit +// --------- + +$orbit-bullet-background: $medium-gray; +$orbit-bullet-background-active: $dark-gray; +$orbit-bullet-diameter: 1.2rem; +$orbit-bullet-margin: 0.1rem; +$orbit-bullet-margin-top: 0.8rem; +$orbit-bullet-margin-bottom: 0.8rem; +$orbit-caption-background: rgba($black, 0.5); +$orbit-caption-padding: 1rem; +$orbit-control-background-hover: rgba($black, 0.5); +$orbit-control-padding: 1rem; +$orbit-control-zindex: 10; + +// 26. Pagination +// -------------- + +$pagination-font-size: rem-calc(14); +$pagination-margin-bottom: $global-margin; +$pagination-item-color: $black; +$pagination-item-padding: rem-calc(3 10); +$pagination-item-spacing: rem-calc(1); +$pagination-radius: $global-radius; +$pagination-item-background-hover: $light-gray; +$pagination-item-background-current: $primary-color; +$pagination-item-color-current: foreground($pagination-item-background-current); +$pagination-item-color-disabled: $medium-gray; +$pagination-ellipsis-color: $black; +$pagination-mobile-items: false; +$pagination-arrows: true; + +// 27. Progress Bar +// ---------------- + +$progress-height: 1rem; +$progress-background: $medium-gray; +$progress-margin-bottom: $global-margin; +$progress-meter-background: $primary-color; +$progress-radius: $global-radius; + +// 28. Reveal +// ---------- + +$reveal-background: $white; +$reveal-width: 600px; +$reveal-max-width: $global-width; +$reveal-padding: $global-padding; +$reveal-border: 1px solid $medium-gray; +$reveal-radius: $global-radius; +$reveal-zindex: 1005; +$reveal-overlay-background: rgba($black, 0.45); + +// 29. Slider +// ---------- + +$slider-width-vertical: 0.5rem; +$slider-transition: all 0.2s ease-in-out; +$slider-height: 0.5rem; +$slider-background: $light-gray; +$slider-fill-background: $medium-gray; +$slider-handle-height: 1.4rem; +$slider-handle-width: 1.4rem; +$slider-handle-background: $primary-color; +$slider-opacity-disabled: 0.25; +$slider-radius: $global-radius; + +// 30. Switch +// ---------- + +$switch-background: $medium-gray; +$switch-background-active: $primary-color; +$switch-height: 2rem; +$switch-height-tiny: 1.5rem; +$switch-height-small: 1.75rem; +$switch-height-large: 2.5rem; +$switch-radius: $global-radius; +$switch-margin: $global-margin; +$switch-paddle-background: $white; +$switch-paddle-offset: 0.25rem; +$switch-paddle-radius: $global-radius; +$switch-paddle-transition: all 0.25s ease-out; + +// 31. Table +// --------- + +$table-background: $white; +$table-color-scale: 5%; +$table-border: 0px solid smart-scale($table-background, $table-color-scale); +$table-padding: rem-calc(8 10 10); +$table-hover-scale: 2%; +$table-row-hover: darken($table-background, $table-hover-scale); +$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale); +$table-striped-background: smart-scale($table-background, $table-color-scale); +$table-stripe: even; +$table-head-background: smart-scale($table-background, $table-color-scale / 2); +$table-foot-background: smart-scale($table-background, $table-color-scale); +$table-head-font-color: $body-font-color; +$show-header-for-stacked: false; + +// 32. Tabs +// -------- + +$tab-margin: 0; +$tab-background: $white; +$tab-background-active: $light-gray; +$tab-item-font-size: rem-calc(12); +$tab-item-background-hover: $white; +$tab-item-padding: 1.25rem 1.5rem; +$tab-expand-max: 6; +$tab-content-background: $white; +$tab-content-border: $light-gray; +$tab-content-color: foreground($tab-background, $primary-color); +$tab-content-padding: 1rem; + +// 33. Thumbnail +// ------------- + +$thumbnail-border: solid 4px $white; +$thumbnail-margin-bottom: $global-margin; +$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2); +$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5); +$thumbnail-transition: box-shadow 200ms ease-out; +$thumbnail-radius: $global-radius; + +// 34. Title Bar +// ------------- + +$titlebar-background: $black; +$titlebar-color: $white; +$titlebar-padding: 0.5rem; +$titlebar-text-font-weight: bold; +$titlebar-icon-color: $sopds-title-color; +$titlebar-icon-color-hover: $sopds-hover-color; +$titlebar-icon-spacing: 0.25rem; + +// 35. Tooltip +// ----------- + +$has-tip-font-weight: $global-weight-bold; +//$has-tip-border-bottom: dotted 1px $dark-gray; +$has-tip-border-bottom: none 0px $dark-gray; +$tooltip-background-color: $black; +$tooltip-color: $white; +$tooltip-padding: 0.75rem; +$tooltip-font-size: $small-font-size; +$tooltip-pip-width: 0.75rem; +$tooltip-pip-height: $tooltip-pip-width * 0.866; +$tooltip-radius: $global-radius; + +// 36. Top Bar +// ----------- + +$topbar-padding: 0.5rem; +$topbar-background: $sopds-topbar-bg-color; +$topbar-submenu-background: $topbar-background; +$topbar-title-spacing: 1rem; +$topbar-input-width: 200px; +$topbar-unstack-breakpoint: small; diff --git a/assets/sopds-sass/scss/sopds.scss b/assets/sopds-sass/scss/sopds.scss new file mode 100644 index 0000000000000000000000000000000000000000..e6c834b55ae1f2c0ab68685a69a980276d6ab9a1 --- /dev/null +++ b/assets/sopds-sass/scss/sopds.scss @@ -0,0 +1,73 @@ +@charset 'utf-8'; + +@import 'settings'; +@import 'foundation'; +@import 'motion-ui'; + +@include foundation-global-styles; +@include foundation-grid; +// @include foundation-flex-grid; +@include foundation-typography; +@include foundation-button; +@include foundation-forms; +// @include foundation-range-input; +@include foundation-accordion; +@include foundation-accordion-menu; +@include foundation-badge; +@include foundation-breadcrumbs; +@include foundation-button-group; +@include foundation-callout; +@include foundation-close-button; +@include foundation-menu; +@include foundation-menu-icon; +@include foundation-drilldown-menu; +@include foundation-dropdown; +@include foundation-dropdown-menu; +@include foundation-flex-video; +@include foundation-label; +@include foundation-media-object; +@include foundation-off-canvas; +@include foundation-orbit; +@include foundation-pagination; +@include foundation-progress-bar; +// @include foundation-progress-element; +// @include foundation-meter-element; +@include foundation-slider; +@include foundation-sticky; +@include foundation-reveal; +@include foundation-switch; +@include foundation-table; +@include foundation-tabs; +@include foundation-thumbnail; +@include foundation-title-bar; +@include foundation-tooltip; +@include foundation-top-bar; +@include foundation-visibility-classes; +@include foundation-float-classes; +// @include foundation-flex-classes; + +@include motion-ui-transitions; +@include motion-ui-animations; + +.top-bar { +@extend .top-bar; + ul.menu { + a { color : $sopds-title-color; } + a:hover { color: $sopds-hover-color; } + } + .title-bar-title { color : $sopds-title-color; } +} + +.sopdsbg { + background-color: $sopds-bg-color; + a { color : $sopds-title-color; } + a:hover { color: $sopds-hover-color; } + color : $sopds-title-color; +} + +.sopdsmenu { + background-color: $sopds-menu-bg-color; + a { color : $sopds-menu-color; } + a:hover { background-color: $sopds-menu-bg-hover-color; } + color : $sopds-menu-color; +} diff --git a/conf/sopds.conf b/conf/sopds.conf deleted file mode 100644 index bf5c49d31c901c28ac4f56910de049221eb72e4e..0000000000000000000000000000000000000000 --- a/conf/sopds.conf +++ /dev/null @@ -1,202 +0,0 @@ -# Simple OPDS Catalog config file -# -[global] -db_name = sopds -db_user = sopds -db_pass = sopds -db_host = localhost -db_charset = utf8 - -#Здесь необходимо укзать путь к каталогу в котором расположена ваша коллектция книг -root_lib = /mnt/SATA1TB-2/КНИГИ/BOOKS -#root_lib = /mnt/SATA1TB-2/КНИГИ/TEST - -#Списк форматов, которые будут включаться в каталог -formats = .pdf .djvu .fb2 .epub - -#cgi_path и wsgi_path - пути к соответсвующим скриптам -#скорее всего стоит их оставить по умолчанию -#если закомментировать эти параметры, то будет применены параметры по умолчанию: -#cgi_path=sopds.cgi, wsgi_path=sopds.wsgi -cgi_path=sopds.cgi -wsgi_path=sopds.wsgi - -# Количество выдаваемых строк на одну страницу -maxitems = 60 - -# dublicates_find - управляет способом поиска дубликатов книг в базе данных -# dublicates_find = no - поиск дубликатов не производится (ранее найденные дубликаты так и остаются с пометкой дубликата в базе данных) -# dublicates_find = yes - производится поиск дубликатов на основании спсика авторов и названия произведения -# dublicates_find = strong - производится поиск дубликатов на основании полей title, format и filesize -# dublicates_find = clear - производится очистка данных о дубликатах в БД -# при этом дубликат всегда помещается в базу, но помечается как дубликат и может исключаться из выдачи -# при поиске по наименованиям и по авторам. В случае поиска по каталогам, книги, помеченные как дубликаты все равно будут показываться -dublicates_find = yes - -# Указывает следует ли показывать книги, помеченные при сканировании как дубликаты в сортировках по наименованию и автору -dublicates_show = no - -# Извлекать метаинформацию из книг fb2 -fb2parse = yes - -# cover_show - способ показа обложек: -# 0 - не показывать, -# 1 - извлекать обложки на лету и показывать -# -cover_show = 1 - -# Предположительно столько байт от начала файла fb2 необходимо считать, чтобы получить необходимую метаинформацию (только description), если 0 то парсится весь файл -# при использование числа отличного от 0 возможны ошибки (например description очень длинный и занимает более, чем указанное число байт) -# при установленном cover_enable=yes значение fb2size вне зависимости от установки считается равным 0 -# Экспериментальная штука, лучше оставить равным 0 -fb2hsize = 0 - -# zipscan = yes - Приводит к сканированию файлов архива -zipscan = yes - -# ziprescan = no - Предотвращает повторное сканирование всего zip-архива -# Но в этом случае, если в архиве произойдут изменения (удаления, добавления), то сканер этого не "заметит" -ziprescan = no - -# Указываем какая кодировка для названий файлов используется в ZIP-архивах -# доступные кодировки: cp437, cp866, cp1251, utf-8 -# по умолчанию применяется кодировка cp437 -# Поскольку в самом ZIP архиве сведения о кодировке, в которой находятся имена файлов - отсутствуют -# то автоматически определить правильную кодировку для имен файлов не представляется возможным -# поэтому для того чтобы кириллические имена файлов не ваыглядели как крякозябры следует применять кодировку cp866 -# по умолчанию также используется значение zip_codepage = cp866 -zip_codepage = cp866 - -# Установка delete_logical=yes приведет к тому, что при обнаружении сканером, что книга удалена, запись в БД об этой книге будет удалена логически (avail=0) -# Если delete_logical=no, то произойдет физическое удаление таких записей из базы данных -delete_logical=no - -# При таком количестве авторов в выдаче по авторам следующий уровень сортировки предоставляться уже не будет -splitauthors = 300 -# При таком количестве наименований книг в выдаче по наименованиям следующий уровень сортировки предоставляться уже не будет -splittitles = 300 - -# Путь к конвертеру из fb2 в epub -# (При наличии нескольких конвертеров путь должен быть только один, два конвертера одновременно все равно работать не будут) -# Если закомментировать эту опцию, либо конвертер не будет найден по указанному пути -# то скачать книги в формате EPUB предлагаться не будет -# Опция temp_dir указывает в каком каталоге создавать временные файлы во время преобразования fb2toepub -#fb2toepub=../fb2toepub/unix_dist/fb2toepub -#fb2toepub=../fb2epub/fb2epub -#fb2toepub=../fb2conv/fb2epub -#fb2tomobi=../fb2conv/fb2mobi -temp_dir=/tmp - -# При установке опции single_commit = yes, данные записываемые сканером в БД коммитятся один раз при окончании сканирования -# Если single_commit = no то коммиты происходят кажды раз при добавлении книги в БД. -# Применение однократного коммита несколько ускоряет сканирование. -# По умолчанию будет считаться что single_commit=no -single_commit = yes - -# Установка параметра title_as_filename = yes приведет к тому, что при скачивании книги имя файла будет изменено -# на транслитерацию заголовка (title) книги -# По умолчанию считается что title_as_filename = no -title_as_filename = yes - -# alphabet_menu = yes в сортировака по авторам, по наименованиям и по жанрам приведет к появлению доп.меню выбора алфавита -# по умолчанию alphabet_menu=yes -alphabet_menu = yes - -# new_period = N - количество суток в течении которых добавленные книги считаются новыми, по умолчанию 7 дней -# Если new_period=0, то меню новинок не будет выводится вовсе -# по умолчанию new_period = 7 -new_period = 7 - -# Установка параметра book_shelf = yes приведет к появлению в основном меню Книжной полки для пользователя (если настроена авторизация web-сервером) -# Здесь будут запоминаться скачанные пользователем книги. Это удобно при использовании нескольких устройств. -# При установке book_shelf = no Книжная полка в главном меню отображаться не будет, также не будет происходить запоминание загружаемых книг -book_shelf = yes - -# Настройка логов -# Параметр logfile задает имя файла, куда будут складываться логи выполнения скрипта sopds-scan.py -# (путь задавать не нужно - логи будут находится в папке logs) -# По умолчанию logfile = scan.log -# loglevel может быть одним из следующих значений: debug, info, warning, error, critical, none. -# По умолчанию loglevel=info -logfile=scan.log - -# loglevel может быть одним из следующих значений: debug, info, warning, error, critical, none. -# По умолчанию loglevel=info -loglevel=info - -[scand] -# pid_file должен содержать путь к pid-файлу процесса OPDS-сканера. Для демона sopdsd.py по указанному пути должен быть доступ на запись -# по умолчанию pid_file=/tmp/sopds.pid -pid_file = /tmp/sopds-scan.pid - -# Если daemon = yes, то демон sopdsd.py запустит встроенный SCAN-cервер -# по умолчнию daemon = yes -daemon = yes - -# scan_day_of_week содержит день недели (1=пн, 7=вс, 0=каждый день) когда должен запускаться процесс сканирования -# по умолчанию scan_day_of_week=0 -scan_day_of_week = 0 - -# scan_time содержит время в формате HH:MM когда необходимо запустить сканирование -# по умолчанию scan_time=00:00 -scan_time = 00:00 - -# scan_interval содержит интервал (в минутах) между сканированиями, например если scan_interval=120, а scan_time=00:00, -# то сканирование будет запускаться каждые 2 часа начиная с 00:00 (т.е. в 00:00, 02:00, 04:00, 06:00, и т.д.) -# если сканирование не будет завершено в течение указанного интервала, но новое сканирование запустится сразу после окончания предидущего -# Установка scan_interval=0 приводит к однократному выполнению сканирования в установленное опцией scan_time время -# по умолчанию scan_intervel = 0 -scan_interval = 360 - -# scan_on_start определяет необходимость запуска сканирования при старте sopdsd.py -# если scan_on_start = yes , то при запуске sopdsd.py сразу же запустится сканирование -# по умолчанию scan_on_start = yes -scan_on_start = yes - -# Параметр logfile задает имя файла, куда будут складываться логи от SCAND-демона (путь задавать не нужно - логи будут находится в папке logs) -# По умолчанию logfile = sopds-scand.log -logfile = sopds-scand.log - -[httpd] -# pid_file должен содержать путь к pid-файлу процесса OPDS-сервера. Для демона sopdsd.py по указанному пути должен быть доступ на запись -# по умолчанию pid_file=/tmp/sopds-http.pid -pid_file = /tmp/sopds-http.pid - -# Префиксы после строки адреса, которые будут использованы для определения формата вывода (OPDS или WEB) -# по умолчанию, если никакой префикс не подходит, вывод будет в OPDS формате -opdsprefix = '/opds' -webprefix = '/web' - -# Если daemon = yes, то демон sopdsd.py запустит встроенный HTTP-OPDS-сервер -# по умолчнию daemon = yes -daemon = yes - -# Номер TCP порта на котором будет работать OPDS-сервер -# по умолчанию port = 8081 -port = 8081 - -# Адрес на котором будет запущено OPDS-сервер -# 0.0.0.0 - указывает что сервер будет работать на всех доступных адресах сервера -bind_address = 0.0.0.0 - -# Если auth = yes, то встроенный httpd-сервер будет выполнять Basic-авторизацию на основании строки auth_accounts -# по умолчнию auth = no -auth = yes - -# Строка accounts должна содержать разделенные пробелам пары user:password -# на основании данных этого параметра при включенном auth = yes будет происходить авторизация на встроенном -# OPDS-сервере -accounts = user:pass user1:pass1 - -# Параметр logfile задает имя файла, куда будут складываться логи от HTTP-демона (путь задавать не нужно - логи будут находится в папке logs) -# По умолчанию logfile = access.log -logfile = sopds-httpd.log - -[site] -id=http://sopds.ru/ -title=SOPDS.RU | OPDS Catalog -icon=http://sopds.ru/favicon.ico -autor=Dmitry Shelepnev -url=http://sopds.ru -email=admin@sopds.ru -main_title=ROOT of Simple OPDS Catalog diff --git a/fb2conv/fb2conv-1.5.2.src.zip b/convert/fb2conv/fb2conv-1.5.2.src.zip old mode 100755 new mode 100644 similarity index 100% rename from fb2conv/fb2conv-1.5.2.src.zip rename to convert/fb2conv/fb2conv-1.5.2.src.zip diff --git a/fb2conv/fb2epub b/convert/fb2conv/fb2epub old mode 100755 new mode 100644 similarity index 100% rename from fb2conv/fb2epub rename to convert/fb2conv/fb2epub diff --git a/fb2conv/fb2mobi b/convert/fb2conv/fb2mobi old mode 100755 new mode 100644 similarity index 100% rename from fb2conv/fb2mobi rename to convert/fb2conv/fb2mobi diff --git a/fb2conv/kindlegen_linux_2.6_i386_v2_9.tar.gz b/convert/fb2conv/kindlegen_linux_2.6_i386_v2_9.tar.gz old mode 100755 new mode 100644 similarity index 100% rename from fb2conv/kindlegen_linux_2.6_i386_v2_9.tar.gz rename to convert/fb2conv/kindlegen_linux_2.6_i386_v2_9.tar.gz diff --git a/fb2epub/fb2epub b/convert/fb2epub/fb2epub old mode 100755 new mode 100644 similarity index 100% rename from fb2epub/fb2epub rename to convert/fb2epub/fb2epub diff --git a/fb2epub/fb2epub-0.3.0.jar b/convert/fb2epub/fb2epub-0.3.0.jar old mode 100755 new mode 100644 similarity index 100% rename from fb2epub/fb2epub-0.3.0.jar rename to convert/fb2epub/fb2epub-0.3.0.jar diff --git a/convert/fb2epub/fb2epub.cmd b/convert/fb2epub/fb2epub.cmd new file mode 100644 index 0000000000000000000000000000000000000000..23e7c9f77b6b983101aed16bf4bed43f6e5cd1b9 --- /dev/null +++ b/convert/fb2epub/fb2epub.cmd @@ -0,0 +1,2 @@ +@set run_path=%~dp0 +java -jar "%run_path%\fb2epub-0.3.0.jar" %1 %2 diff --git a/fb2toepub/fb2toepub-1.0_4.zip b/convert/fb2toepub/fb2toepub-1.0_4.zip similarity index 100% rename from fb2toepub/fb2toepub-1.0_4.zip rename to convert/fb2toepub/fb2toepub-1.0_4.zip diff --git a/db/db.sql b/db/db.sql deleted file mode 100644 index 7effd9a949b290bed2b7a0eed63e9cca78412d29..0000000000000000000000000000000000000000 --- a/db/db.sql +++ /dev/null @@ -1,3 +0,0 @@ -create database if not exists sopds default charset=utf8; -grant all on sopds.* to 'sopds'@'localhost' identified by 'sopds'; -commit; diff --git a/db/db_create.sh b/db/db_create.sh deleted file mode 100755 index ad25f67a6fb9338b42c40523514ed0efcf47edc1..0000000000000000000000000000000000000000 --- a/db/db_create.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -run_path=`dirname $0` -script_db=$run_path'/db.sql' -script_tables=$run_path'/tables.sql' -script_genres=$run_path'/genres.sql' - -mysql mysql < $script_db -mysql sopds < $script_tables -mysql sopds < $script_genres diff --git a/db/genres.mksql b/db/genres.mksql deleted file mode 100755 index 9c51663cc9a2697e93b2afe0037b6762eec82d88..0000000000000000000000000000000000000000 --- a/db/genres.mksql +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -echo "SET NAMES 'utf8';" -echo "SET CHARACTER SET utf8;" -echo - -cat genres.txt | grep -v '#' | awk -F'@' '{gsub(/^ +| +$/,"",$1)} {gsub(/^ +| +$/,"",$2)} {gsub(/^ +| +$/,"",$3)} {print "insert into genres(genre,subsection,section) values(\""$1"\",\""$2"\",\""$3"\");"}' -echo "commit;" - diff --git a/db/genres.sql b/db/genres.sql deleted file mode 100644 index b44f7a8100c0121ad9a3e897dd1f51bf5c68c16a..0000000000000000000000000000000000000000 --- a/db/genres.sql +++ /dev/null @@ -1,232 +0,0 @@ -SET NAMES 'utf8'; -SET CHARACTER SET utf8; - -insert into genres(genre,subsection,section) values("economics_ref","Деловая литература","Деловая литература"); -insert into genres(genre,subsection,section) values("popular_business","Карьера, кадры","Деловая литература"); -insert into genres(genre,subsection,section) values("org_behavior","Маркетинг, PR","Деловая литература"); -insert into genres(genre,subsection,section) values("banking","Финансы","Деловая литература"); -insert into genres(genre,subsection,section) values("economics","Экономика","Деловая литература"); -insert into genres(genre,subsection,section) values("det_action","Боевик","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("detective","Детективы","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_irony","Иронический детектив, дамский детективный роман","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_history","Исторический детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_classic","Классический детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_crime","Криминальный детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_hard","Крутой детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_political","Политический детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_police","Полицейский детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_maniac","Про маньяков","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_su","Советский детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("thriller","Триллер","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("det_espionage","Шпионский детектив","Детективы и Триллеры"); -insert into genres(genre,subsection,section) values("nonf_biography","Биографии и Мемуары","Документальная литература"); -insert into genres(genre,subsection,section) values("nonf_military","Военная документалистика и аналитика","Документальная литература"); -insert into genres(genre,subsection,section) values("military_special","Военное дело","Документальная литература"); -insert into genres(genre,subsection,section) values("travel_notes","География, путевые заметки","Документальная литература"); -insert into genres(genre,subsection,section) values("nonfiction","Документальная литература","Документальная литература"); -insert into genres(genre,subsection,section) values("nonf_publicism","Публицистика","Документальная литература"); -insert into genres(genre,subsection,section) values("auto_regulations","Автомобили и ПДД","Дом и семья"); -insert into genres(genre,subsection,section) values("home_sport","Боевые искусства, спорт","Дом и семья"); -insert into genres(genre,subsection,section) values("home_pets","Домашние животные","Дом и семья"); -insert into genres(genre,subsection,section) values("home","Домоводство","Дом и семья"); -insert into genres(genre,subsection,section) values("home_health","Здоровье","Дом и семья"); -insert into genres(genre,subsection,section) values("home_collecting","Коллекционирование","Дом и семья"); -insert into genres(genre,subsection,section) values("home_cooking","Кулинария","Дом и семья"); -insert into genres(genre,subsection,section) values("sci_pedagogy","Педагогика, воспитание детей, литература для родителей","Дом и семья"); -insert into genres(genre,subsection,section) values("home_entertain","Развлечения","Дом и семья"); -insert into genres(genre,subsection,section) values("home_garden","Сад и огород","Дом и семья"); -insert into genres(genre,subsection,section) values("home_diy","Сделай сам","Дом и семья"); -insert into genres(genre,subsection,section) values("family","Семейные отношения","Дом и семья"); -insert into genres(genre,subsection,section) values("home_sex","Семейные отношения, секс","Дом и семья"); -insert into genres(genre,subsection,section) values("home_crafts","Хобби и ремесла","Дом и семья"); -insert into genres(genre,subsection,section) values("drama_antique","Античная драма","Драматургия"); -insert into genres(genre,subsection,section) values("drama","Драма","Драматургия"); -insert into genres(genre,subsection,section) values("dramaturgy","Драматургия","Драматургия"); -insert into genres(genre,subsection,section) values("comedy","Комедия","Драматургия"); -insert into genres(genre,subsection,section) values("vaudeville","Мистерия, буффонада, водевиль","Драматургия"); -insert into genres(genre,subsection,section) values("screenplays","Сценарий","Драматургия"); -insert into genres(genre,subsection,section) values("tragedy","Трагедия","Драматургия"); -insert into genres(genre,subsection,section) values("painting","Живопись, альбомы, иллюстрированные каталоги","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("design","Искусство и Дизайн","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("art_criticism","Искусствоведение","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("cine","Кино","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("nonf_criticism","Критика","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("sci_culture","Культурология","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("art_world_culture","Мировая художественная культура","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("music","Музыка","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("notes","Партитуры","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("architecture_book","Скульптура и архитектура","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("theatre","Театр","Искусство, Искусствоведение, Дизайн"); -insert into genres(genre,subsection,section) values("computers","Зарубежная компьютерная, околокомпьютерная литература","Компьютеры и Интернет"); -insert into genres(genre,subsection,section) values("аппаратное обеспечение, цифровая обработка сигналов (comp_hard","Компьютерное 'железо'","Компьютеры и Интернет"); -insert into genres(genre,subsection,section) values("comp_www","ОС и Сети, интернет","Компьютеры и Интернет"); -insert into genres(genre,subsection,section) values("comp_db","Программирование, программы, базы данных","Компьютеры и Интернет"); -insert into genres(genre,subsection,section) values("tbg_computers","Учебные пособия, самоучители","Компьютеры и Интернет"); -insert into genres(genre,subsection,section) values("children","Детская литература","Литература для детей"); -insert into genres(genre,subsection,section) values("child_education","Детская образовательная литература","Литература для детей"); -insert into genres(genre,subsection,section) values("child_det","Детская остросюжетная литература","Литература для детей"); -insert into genres(genre,subsection,section) values("foreign_children","Зарубежная литература для детей","Литература для детей"); -insert into genres(genre,subsection,section) values("prose_game","Игры, упражнения для детей","Литература для детей"); -insert into genres(genre,subsection,section) values("child_classical","Классическая детская литература","Литература для детей"); -insert into genres(genre,subsection,section) values("child_prose","Проза для детей","Литература для детей"); -insert into genres(genre,subsection,section) values("child_tale_rus","Русские сказки","Литература для детей"); -insert into genres(genre,subsection,section) values("child_tale","Сказки народов мира","Литература для детей"); -insert into genres(genre,subsection,section) values("child_verse","Стихи для детей","Литература для детей"); -insert into genres(genre,subsection,section) values("child_sf","Фантастика для детей","Литература для детей"); -insert into genres(genre,subsection,section) values("love_history","Исторические любовные романы","Любовные романы"); -insert into genres(genre,subsection,section) values("love_short","Короткие любовные романы","Любовные романы"); -insert into genres(genre,subsection,section) values("love_sf","Любовное фэнтези, любовно-фантастические романы","Любовные романы"); -insert into genres(genre,subsection,section) values("love","Любовные романы","Любовные романы"); -insert into genres(genre,subsection,section) values("love_detective","Остросюжетные любовные романы","Любовные романы"); -insert into genres(genre,subsection,section) values("love_hard","Порно","Любовные романы"); -insert into genres(genre,subsection,section) values("love_contemporary","Современные любовные романы","Любовные романы"); -insert into genres(genre,subsection,section) values("love_erotica","Эротическая литература","Любовные романы"); -insert into genres(genre,subsection,section) values("sci_medicine_alternative","Альтернативная медицина","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_theories","Альтернативные науки и научные теории","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_cosmos","Астрономия и Космос","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_biology","Биология, биофизика, биохимия","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_botany","Ботаника","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_veterinary","Ветеринария","Наука, Образование"); -insert into genres(genre,subsection,section) values("military_history","Военная история","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_oriental","Востоковедение","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_geo","Геология и география","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_state","Государство и право","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_popular","Зарубежная образовательная литература, зарубежная прикладная, научно-популярная литература","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_zoo","Зоология","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_history","История","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_philology","Литературоведение","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_math","Математика","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_medicine","Медицина","Наука, Образование"); -insert into genres(genre,subsection,section) values("science","Научная литература","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_social_studies","Обществознание, социология","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_politics","Политика","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_psychology","Психология и психотерапия","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_phys","Физика","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_philosophy","Философия","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_chem","Химия","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_ecology","Экология","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_economy","Экономика","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_juris","Юриспруденция","Наука, Образование"); -insert into genres(genre,subsection,section) values("sci_linguistic","Языкознание, иностранные языки","Наука, Образование"); -insert into genres(genre,subsection,section) values("palindromes","Визуальная и экспериментальная поэзия, верлибры, палиндромы","Поэзия"); -insert into genres(genre,subsection,section) values("poetry_for_classical","Классическая зарубежная поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("poetry_classical","Классическая поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("poetry_rus_classical","Классическая русская поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("lyrics","Лирика","Поэзия"); -insert into genres(genre,subsection,section) values("song_poetry","Песенная поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("poetry","Поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("poetry_east","Поэзия Востока","Поэзия"); -insert into genres(genre,subsection,section) values("poem","Поэма, эпическая поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("poetry_for_modern","Современная зарубежная поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("poetry_modern","Современная поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("poetry_rus_modern","Современная русская поэзия","Поэзия"); -insert into genres(genre,subsection,section) values("humor_verse","Юмористические стихи, басни","Поэзия"); -insert into genres(genre,subsection,section) values("adv_story","Авантюрный роман","Приключения"); -insert into genres(genre,subsection,section) values("adv_indian","Вестерн, про индейцев","Приключения"); -insert into genres(genre,subsection,section) values("adv_history","Исторические приключения","Приключения"); -insert into genres(genre,subsection,section) values("adv_maritime","Морские приключения","Приключения"); -insert into genres(genre,subsection,section) values("adventure","Приключения","Приключения"); -insert into genres(genre,subsection,section) values("adv_modern","Приключения в современном мире","Приключения"); -insert into genres(genre,subsection,section) values("child_adv","Приключения для детей и подростков","Приключения"); -insert into genres(genre,subsection,section) values("adv_animal","Природа и животные","Приключения"); -insert into genres(genre,subsection,section) values("adv_geo","Путешествия и география","Приключения"); -insert into genres(genre,subsection,section) values("tale_chivalry","Рыцарский роман","Приключения"); -insert into genres(genre,subsection,section) values("aphorisms","Афоризмы, цитаты","Проза"); -insert into genres(genre,subsection,section) values("gothic_novel","Готический роман","Проза"); -insert into genres(genre,subsection,section) values("foreign_prose","Зарубежная классическая проза","Проза"); -insert into genres(genre,subsection,section) values("prose_history","Историческая проза","Проза"); -insert into genres(genre,subsection,section) values("prose_classic","Классическая проза","Проза"); -insert into genres(genre,subsection,section) values("literature_18","Классическая проза XVII-XVIII веков","Проза"); -insert into genres(genre,subsection,section) values("literature_19","Классическая проза ХIX века","Проза"); -insert into genres(genre,subsection,section) values("literature_20","Классическая проза ХX века","Проза"); -insert into genres(genre,subsection,section) values("prose_counter","Контркультура","Проза"); -insert into genres(genre,subsection,section) values("prose_magic","Магический реализм","Проза"); -insert into genres(genre,subsection,section) values("story","Малые литературные формы прозы: рассказы, эссе, новеллы, феерия","Проза"); -insert into genres(genre,subsection,section) values("prose","Проза","Проза"); -insert into genres(genre,subsection,section) values("prose_military","Проза о войне","Проза"); -insert into genres(genre,subsection,section) values("great_story","Роман, повесть","Проза"); -insert into genres(genre,subsection,section) values("prose_rus_classic","Русская классическая проза","Проза"); -insert into genres(genre,subsection,section) values("prose_su_classics","Советская классическая проза","Проза"); -insert into genres(genre,subsection,section) values("prose_contemporary","Современная русская и зарубежная проза","Проза"); -insert into genres(genre,subsection,section) values("foreign_antique","Средневековая классическая проза","Проза"); -insert into genres(genre,subsection,section) values("prose_abs","Фантасмагория, абсурдистская проза","Проза"); -insert into genres(genre,subsection,section) values("prose_neformatny","Экспериментальная, неформатная проза","Проза"); -insert into genres(genre,subsection,section) values("epistolary_fiction","Эпистолярная проза","Проза"); -insert into genres(genre,subsection,section) values("periodic","Журналы, газеты","Прочее"); -insert into genres(genre,subsection,section) values("comics","Комиксы","Прочее"); -insert into genres(genre,subsection,section) values("unfinished","Незавершенное","Прочее"); -insert into genres(genre,subsection,section) values("other","Неотсортированное","Прочее"); -insert into genres(genre,subsection,section) values("network_literature","Самиздат, сетевая литература","Прочее"); -insert into genres(genre,subsection,section) values("fanfiction","Фанфик","Прочее"); -insert into genres(genre,subsection,section) values("astrology","Астрология и хиромантия","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_budda","Буддизм","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_hinduism","Индуизм","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_islam","Ислам","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_judaism","Иудаизм","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_catholicism","Католицизм","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_orthodoxy","Православие","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_protestantism","Протестантизм","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("sci_religion","Религиоведение","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion","Религия, религиозная литература","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_self","Самосовершенствование","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_christianity","Христианство","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_esoterics","Эзотерика, эзотерическая литература","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("religion_paganism","Язычество","Религия, духовность, эзотерика"); -insert into genres(genre,subsection,section) values("geo_guides","Путеводители, карты, атласы","Справочная литература"); -insert into genres(genre,subsection,section) values("ref_guide","Руководства","Справочная литература"); -insert into genres(genre,subsection,section) values("ref_dict","Словари","Справочная литература"); -insert into genres(genre,subsection,section) values("reference","Справочная литература","Справочная литература"); -insert into genres(genre,subsection,section) values("ref_ref","Справочники","Справочная литература"); -insert into genres(genre,subsection,section) values("ref_encyc","Энциклопедии","Справочная литература"); -insert into genres(genre,subsection,section) values("antique","antique","Старинное"); -insert into genres(genre,subsection,section) values("antique_ant","Античная литература","Старинное"); -insert into genres(genre,subsection,section) values("antique_east","Древневосточная литература","Старинное"); -insert into genres(genre,subsection,section) values("antique_russian","Древнерусская литература","Старинное"); -insert into genres(genre,subsection,section) values("antique_european","Европейская старинная литература","Старинное"); -insert into genres(genre,subsection,section) values("auto_business","Автодело","Техника"); -insert into genres(genre,subsection,section) values("military_weapon","Военное дело, военная техника и вооружение","Техника"); -insert into genres(genre,subsection,section) values("equ_history","История техники","Техника"); -insert into genres(genre,subsection,section) values("sci_metal","Металлургия","Техника"); -insert into genres(genre,subsection,section) values("sci_radio","Радиоэлектроника","Техника"); -insert into genres(genre,subsection,section) values("sci_build","Строительство и сопромат","Техника"); -insert into genres(genre,subsection,section) values("sci_tech","Технические науки","Техника"); -insert into genres(genre,subsection,section) values("sci_transport","Транспорт и авиация","Техника"); -insert into genres(genre,subsection,section) values("sci_textbook","Учебники и пособия","Учебники и пособия"); -insert into genres(genre,subsection,section) values("tbg_higher","Учебники и пособия ВУЗов","Учебники и пособия"); -insert into genres(genre,subsection,section) values("tbg_secondary","Учебники и пособия для среднего и специального образования","Учебники и пособия"); -insert into genres(genre,subsection,section) values("tbg_school","Школьные учебники и пособия, рефераты, шпаргалки","Учебники и пособия"); -insert into genres(genre,subsection,section) values("sf_history","Альтернативная история, попаданцы","Фантастика"); -insert into genres(genre,subsection,section) values("sf_action","Боевая фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_heroic","Героическая фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_fantasy_city","Городское фэнтези","Фантастика"); -insert into genres(genre,subsection,section) values("sf_detective","Детективная фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_cyberpunk","Киберпанк","Фантастика"); -insert into genres(genre,subsection,section) values("sf_space","Космическая фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_mystic","Мистика","Фантастика"); -insert into genres(genre,subsection,section) values("fairy_fantasy","Мифологическое фэнтези","Фантастика"); -insert into genres(genre,subsection,section) values("sf","Научная Фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_postapocalyptic","Постапокалипсис","Фантастика"); -insert into genres(genre,subsection,section) values("russian_fantasy","Славянское фэнтези","Фантастика"); -insert into genres(genre,subsection,section) values("modern_tale","Современная сказка","Фантастика"); -insert into genres(genre,subsection,section) values("sf_social","Социально-психологическая фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_stimpank","Стимпанк","Фантастика"); -insert into genres(genre,subsection,section) values("sf_technofantasy","Технофэнтези","Фантастика"); -insert into genres(genre,subsection,section) values("sf_horror","Ужасы","Фантастика"); -insert into genres(genre,subsection,section) values("sf_etc","Фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_fantasy","Фэнтези","Фантастика"); -insert into genres(genre,subsection,section) values("hronoopera","Хроноопера","Фантастика"); -insert into genres(genre,subsection,section) values("sf_epic","Эпическая фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("sf_humor","Юмористическая фантастика","Фантастика"); -insert into genres(genre,subsection,section) values("epic","Былины, эпопея","Фольклор"); -insert into genres(genre,subsection,section) values("child_folklore","Детский фольклор","Фольклор"); -insert into genres(genre,subsection,section) values("antique_myths","Мифы. Легенды. Эпос","Фольклор"); -insert into genres(genre,subsection,section) values("folk_songs","Народные песни","Фольклор"); -insert into genres(genre,subsection,section) values("folk_tale","Народные сказки","Фольклор"); -insert into genres(genre,subsection,section) values("proverbs","Пословицы, поговорки","Фольклор"); -insert into genres(genre,subsection,section) values("folklore","Фольклор, загадки folklore","Фольклор"); -insert into genres(genre,subsection,section) values("limerick","Частушки, прибаутки, потешки","Фольклор"); -insert into genres(genre,subsection,section) values("humor_anecdote","Анекдоты","Юмор"); -insert into genres(genre,subsection,section) values("humor_satire","Сатира","Юмор"); -insert into genres(genre,subsection,section) values("humor","Юмор","Юмор"); -insert into genres(genre,subsection,section) values("humor_prose","Юмористическая проза","Юмор"); -commit; diff --git a/db/genres.txt b/db/genres.txt deleted file mode 100644 index 7a9227e4725bcfd6fd95a6bb992494736c5542da..0000000000000000000000000000000000000000 --- a/db/genres.txt +++ /dev/null @@ -1,250 +0,0 @@ -#Деловая литература - economics_ref @ Деловая литература @ Деловая литература - popular_business @ Карьера, кадры @ Деловая литература - org_behavior @ Маркетинг, PR @ Деловая литература - banking @ Финансы @ Деловая литература - economics @ Экономика @ Деловая литература -#Детективы и Триллеры - det_action @ Боевик @ Детективы и Триллеры - detective @ Детективы @ Детективы и Триллеры - det_irony @ Иронический детектив, дамский детективный роман @ Детективы и Триллеры - det_history @ Исторический детектив @ Детективы и Триллеры - det_classic @ Классический детектив @ Детективы и Триллеры - det_crime @ Криминальный детектив @ Детективы и Триллеры - det_hard @ Крутой детектив @ Детективы и Триллеры - det_political @ Политический детектив @ Детективы и Триллеры - det_police @ Полицейский детектив @ Детективы и Триллеры - det_maniac @ Про маньяков @ Детективы и Триллеры - det_su @ Советский детектив @ Детективы и Триллеры - thriller @ Триллер @ Детективы и Триллеры - det_espionage @ Шпионский детектив @ Детективы и Триллеры -#Документальная литература - nonf_biography @ Биографии и Мемуары @ Документальная литература - nonf_military @ Военная документалистика и аналитика @ Документальная литература - military_special @ Военное дело @ Документальная литература - travel_notes @ География, путевые заметки @ Документальная литература - nonfiction @ Документальная литература @ Документальная литература - nonf_publicism @ Публицистика @ Документальная литература -#Дом и семья - auto_regulations @ Автомобили и ПДД @ Дом и семья - home_sport @ Боевые искусства, спорт @ Дом и семья - home_pets @ Домашние животные @ Дом и семья - home @ Домоводство @ Дом и семья - home_health @ Здоровье @ Дом и семья - home_collecting @ Коллекционирование @ Дом и семья - home_cooking @ Кулинария @ Дом и семья - sci_pedagogy @ Педагогика, воспитание детей, литература для родителей @ Дом и семья - home_entertain @ Развлечения @ Дом и семья - home_garden @ Сад и огород @ Дом и семья - home_diy @ Сделай сам @ Дом и семья - family @ Семейные отношения @ Дом и семья - home_sex @ Семейные отношения, секс @ Дом и семья - home_crafts @ Хобби и ремесла @ Дом и семья -#Драматургия - drama_antique @ Античная драма @ Драматургия - drama @ Драма @ Драматургия - dramaturgy @ Драматургия @ Драматургия - comedy @ Комедия @ Драматургия - vaudeville @ Мистерия, буффонада, водевиль @ Драматургия - screenplays @ Сценарий @ Драматургия - tragedy @ Трагедия @ Драматургия -#Искусство, Искусствоведение, Дизайн - painting @ Живопись, альбомы, иллюстрированные каталоги @ Искусство, Искусствоведение, Дизайн - design @ Искусство и Дизайн @ Искусство, Искусствоведение, Дизайн - art_criticism @ Искусствоведение @ Искусство, Искусствоведение, Дизайн - cine @ Кино @ Искусство, Искусствоведение, Дизайн - nonf_criticism @ Критика @ Искусство, Искусствоведение, Дизайн - sci_culture @ Культурология @ Искусство, Искусствоведение, Дизайн - art_world_culture @ Мировая художественная культура @ Искусство, Искусствоведение, Дизайн - music @ Музыка @ Искусство, Искусствоведение, Дизайн - notes @ Партитуры @ Искусство, Искусствоведение, Дизайн - architecture_book @ Скульптура и архитектура @ Искусство, Искусствоведение, Дизайн - theatre @ Театр @ Искусство, Искусствоведение, Дизайн -#Компьютеры и Интернет - computers @ Зарубежная компьютерная, околокомпьютерная литература @ Компьютеры и Интернет - comp_hard @ Компьютерное 'железо' @ Компьютеры и Интернет - comp_www @ ОС и Сети, интернет @ Компьютеры и Интернет - comp_db @ Программирование, программы, базы данных @ Компьютеры и Интернет - tbg_computers @ Учебные пособия, самоучители @ Компьютеры и Интернет -#Литература для детей - children @ Детская литература @ Литература для детей - child_education @ Детская образовательная литература @ Литература для детей - child_det @ Детская остросюжетная литература @ Литература для детей - foreign_children @ Зарубежная литература для детей @ Литература для детей - prose_game @ Игры, упражнения для детей @ Литература для детей - child_classical @ Классическая детская литература @ Литература для детей - child_prose @ Проза для детей @ Литература для детей - child_tale_rus @ Русские сказки @ Литература для детей - child_tale @ Сказки народов мира @ Литература для детей - child_verse @ Стихи для детей @ Литература для детей - child_sf @ Фантастика для детей @ Литература для детей -#Любовные романы - love_history @ Исторические любовные романы @ Любовные романы - love_short @ Короткие любовные романы @ Любовные романы - love_sf @ Любовное фэнтези, любовно-фантастические романы @ Любовные романы - love @ Любовные романы @ Любовные романы - love_detective @ Остросюжетные любовные романы @ Любовные романы - love_hard @ Порно @ Любовные романы - love_contemporary @ Современные любовные романы @ Любовные романы - love_erotica @ Эротическая литература @ Любовные романы -#Наука, Образование - sci_medicine_alternative @ Альтернативная медицина @ Наука, Образование - sci_theories @ Альтернативные науки и научные теории @ Наука, Образование - sci_cosmos @ Астрономия и Космос @ Наука, Образование - sci_biology @ Биология, биофизика, биохимия @ Наука, Образование - sci_botany @ Ботаника @ Наука, Образование - sci_veterinary @ Ветеринария @ Наука, Образование - military_history @ Военная история @ Наука, Образование - sci_oriental @ Востоковедение @ Наука, Образование - sci_geo @ Геология и география @ Наука, Образование - sci_state @ Государство и право @ Наука, Образование - sci_popular @ Зарубежная образовательная литература, зарубежная прикладная, научно-популярная литература @ Наука, Образование - sci_zoo @ Зоология @ Наука, Образование - sci_history @ История @ Наука, Образование - sci_philology @ Литературоведение @ Наука, Образование - sci_math @ Математика @ Наука, Образование - sci_medicine @ Медицина @ Наука, Образование - science @ Научная литература @ Наука, Образование - sci_social_studies @ Обществознание, социология @ Наука, Образование - sci_politics @ Политика @ Наука, Образование - sci_psychology @ Психология и психотерапия @ Наука, Образование - sci_phys @ Физика @ Наука, Образование - sci_philosophy @ Философия @ Наука, Образование - sci_chem @ Химия @ Наука, Образование - sci_ecology @ Экология @ Наука, Образование - sci_economy @ Экономика @ Наука, Образование - sci_juris @ Юриспруденция @ Наука, Образование - sci_linguistic @ Языкознание, иностранные языки @ Наука, Образование -#Поэзия - palindromes @ Визуальная и экспериментальная поэзия, верлибры, палиндромы @ Поэзия - poetry_for_classical @ Классическая зарубежная поэзия @ Поэзия - poetry_classical @ Классическая поэзия @ Поэзия - poetry_rus_classical @ Классическая русская поэзия @ Поэзия - lyrics @ Лирика @ Поэзия - song_poetry @ Песенная поэзия @ Поэзия - poetry @ Поэзия @ Поэзия - poetry_east @ Поэзия Востока @ Поэзия - poem @ Поэма, эпическая поэзия @ Поэзия - poetry_for_modern @ Современная зарубежная поэзия @ Поэзия - poetry_modern @ Современная поэзия @ Поэзия - poetry_rus_modern @ Современная русская поэзия @ Поэзия - humor_verse @ Юмористические стихи, басни @ Поэзия -#Приключения - adv_story @ Авантюрный роман @ Приключения - adv_indian @ Вестерн, про индейцев @ Приключения - adv_history @ Исторические приключения @ Приключения - adv_maritime @ Морские приключения @ Приключения - adventure @ Приключения @ Приключения - adv_modern @ Приключения в современном мире @ Приключения - child_adv @ Приключения для детей и подростков @ Приключения - adv_animal @ Природа и животные @ Приключения - adv_geo @ Путешествия и география @ Приключения - tale_chivalry @ Рыцарский роман @ Приключения -#Проза - aphorisms @ Афоризмы, цитаты @ Проза - gothic_novel @ Готический роман @ Проза - foreign_prose @ Зарубежная классическая проза @ Проза - prose_history @ Историческая проза @ Проза - prose_classic @ Классическая проза @ Проза - literature_18 @ Классическая проза XVII-XVIII веков @ Проза - literature_19 @ Классическая проза ХIX века @ Проза - literature_20 @ Классическая проза ХX века @ Проза - prose_counter @ Контркультура @ Проза - prose_magic @ Магический реализм @ Проза - story @ Малые литературные формы прозы: рассказы, эссе, новеллы, феерия @ Проза - prose @ Проза @ Проза - prose_military @ Проза о войне @ Проза - great_story @ Роман, повесть @ Проза - prose_rus_classic @ Русская классическая проза @ Проза - prose_su_classics @ Советская классическая проза @ Проза - prose_contemporary @ Современная русская и зарубежная проза @ Проза - foreign_antique @ Средневековая классическая проза @ Проза - prose_abs @ Фантасмагория, абсурдистская проза @ Проза - prose_neformatny @ Экспериментальная, неформатная проза @ Проза - epistolary_fiction @ Эпистолярная проза @ Проза -#Прочее - periodic @ Журналы, газеты @ Прочее - comics @ Комиксы @ Прочее - unfinished @ Незавершенное @ Прочее - other @ Неотсортированное @ Прочее - network_literature @ Самиздат, сетевая литература @ Прочее - fanfiction @ Фанфик @ Прочее -#Религия, духовность, эзотерика - astrology @ Астрология и хиромантия @ Религия, духовность, эзотерика - religion_budda @ Буддизм @ Религия, духовность, эзотерика - religion_hinduism @ Индуизм @ Религия, духовность, эзотерика - religion_islam @ Ислам @ Религия, духовность, эзотерика - religion_judaism @ Иудаизм @ Религия, духовность, эзотерика - religion_catholicism @ Католицизм @ Религия, духовность, эзотерика - religion_orthodoxy @ Православие @ Религия, духовность, эзотерика - religion_protestantism @ Протестантизм @ Религия, духовность, эзотерика - sci_religion @ Религиоведение @ Религия, духовность, эзотерика - religion @ Религия, религиозная литература @ Религия, духовность, эзотерика - religion_self @ Самосовершенствование @ Религия, духовность, эзотерика - religion_christianity @ Христианство @ Религия, духовность, эзотерика - religion_esoterics @ Эзотерика, эзотерическая литература @ Религия, духовность, эзотерика - religion_paganism @ Язычество @ Религия, духовность, эзотерика -#Справочная литература - geo_guides @ Путеводители, карты, атласы @ Справочная литература - ref_guide @ Руководства @ Справочная литература - ref_dict @ Словари @ Справочная литература - reference @ Справочная литература @ Справочная литература - ref_ref @ Справочники @ Справочная литература - ref_encyc @ Энциклопедии @ Справочная литература -#Старинное - antique @ antique @ Старинное - antique_ant @ Античная литература @ Старинное - antique_east @ Древневосточная литература @ Старинное - antique_russian @ Древнерусская литература @ Старинное - antique_european @ Европейская старинная литература @ Старинное -#Техника - auto_business @ Автодело @ Техника - military_weapon @ Военное дело, военная техника и вооружение @ Техника - equ_history @ История техники @ Техника - sci_metal @ Металлургия @ Техника - sci_radio @ Радиоэлектроника @ Техника - sci_build @ Строительство и сопромат @ Техника - sci_tech @ Технические науки @ Техника - sci_transport @ Транспорт и авиация @ Техника -#Учебники и пособия - sci_textbook @ Учебники и пособия @ Учебники и пособия - tbg_higher @ Учебники и пособия ВУЗов @ Учебники и пособия - tbg_secondary @ Учебники и пособия для среднего и специального образования @ Учебники и пособия - tbg_school @ Школьные учебники и пособия, рефераты, шпаргалки @ Учебники и пособия -#Фантастика - sf_history @ Альтернативная история, попаданцы @ Фантастика - sf_action @ Боевая фантастика @ Фантастика - sf_heroic @ Героическая фантастика @ Фантастика - sf_fantasy_city @ Городское фэнтези @ Фантастика - sf_detective @ Детективная фантастика @ Фантастика - sf_cyberpunk @ Киберпанк @ Фантастика - sf_space @ Космическая фантастика @ Фантастика - sf_mystic @ Мистика @ Фантастика - fairy_fantasy @ Мифологическое фэнтези @ Фантастика - sf @ Научная Фантастика @ Фантастика - sf_postapocalyptic @ Постапокалипсис @ Фантастика - russian_fantasy @ Славянское фэнтези @ Фантастика - modern_tale @ Современная сказка @ Фантастика - sf_social @ Социально-психологическая фантастика @ Фантастика - sf_stimpank @ Стимпанк @ Фантастика - sf_technofantasy @ Технофэнтези @ Фантастика - sf_horror @ Ужасы @ Фантастика - sf_etc @ Фантастика @ Фантастика - sf_fantasy @ Фэнтези @ Фантастика - hronoopera @ Хроноопера @ Фантастика - sf_epic @ Эпическая фантастика @ Фантастика - sf_humor @ Юмористическая фантастика @ Фантастика -#Фольклор - epic @ Былины, эпопея @ Фольклор - child_folklore @ Детский фольклор @ Фольклор - antique_myths @ Мифы. Легенды. Эпос @ Фольклор - folk_songs @ Народные песни @ Фольклор - folk_tale @ Народные сказки @ Фольклор - proverbs @ Пословицы, поговорки @ Фольклор - folklore @ Фольклор, загадки folklore @ Фольклор - limerick @ Частушки, прибаутки, потешки @ Фольклор -#Юмор - humor_anecdote @ Анекдоты @ Юмор - humor_satire @ Сатира @ Юмор - humor @ Юмор @ Юмор - humor_prose @ Юмористическая проза @ Юмор diff --git a/db/genres.updsql b/db/genres.updsql deleted file mode 100755 index 60db0be6e62a2156e40b57f57ca0d6b98c4f2768..0000000000000000000000000000000000000000 --- a/db/genres.updsql +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -echo "SET NAMES 'utf8';" -echo "SET CHARACTER SET utf8;" -echo - -cat genres.txt | grep -v '#' | awk -F'@' '{gsub(/^ +| +$/,"",$1)} {gsub(/^ +| +$/,"",$2)} {gsub(/^ +| +$/,"",$3)} {print "update genres set section=\""$3"\", subsection=\""$2"\" where genre=\""$1"\";"}' -echo "commit;" - diff --git a/db/genresupd.sql b/db/genresupd.sql deleted file mode 100644 index 102d672933746dcbbbd55e93d9f551c6201fa67b..0000000000000000000000000000000000000000 --- a/db/genresupd.sql +++ /dev/null @@ -1,232 +0,0 @@ -SET NAMES 'utf8'; -SET CHARACTER SET utf8; - -update genres set section="Деловая литература", subsection="Деловая литература" where genre="economics_ref"; -update genres set section="Деловая литература", subsection="Карьера, кадры" where genre="popular_business"; -update genres set section="Деловая литература", subsection="Маркетинг, PR" where genre="org_behavior"; -update genres set section="Деловая литература", subsection="Финансы" where genre="banking"; -update genres set section="Деловая литература", subsection="Экономика" where genre="economics"; -update genres set section="Детективы и Триллеры", subsection="Боевик" where genre="det_action"; -update genres set section="Детективы и Триллеры", subsection="Детективы" where genre="detective"; -update genres set section="Детективы и Триллеры", subsection="Иронический детектив, дамский детективный роман" where genre="det_irony"; -update genres set section="Детективы и Триллеры", subsection="Исторический детектив" where genre="det_history"; -update genres set section="Детективы и Триллеры", subsection="Классический детектив" where genre="det_classic"; -update genres set section="Детективы и Триллеры", subsection="Криминальный детектив" where genre="det_crime"; -update genres set section="Детективы и Триллеры", subsection="Крутой детектив" where genre="det_hard"; -update genres set section="Детективы и Триллеры", subsection="Политический детектив" where genre="det_political"; -update genres set section="Детективы и Триллеры", subsection="Полицейский детектив" where genre="det_police"; -update genres set section="Детективы и Триллеры", subsection="Про маньяков" where genre="det_maniac"; -update genres set section="Детективы и Триллеры", subsection="Советский детектив" where genre="det_su"; -update genres set section="Детективы и Триллеры", subsection="Триллер" where genre="thriller"; -update genres set section="Детективы и Триллеры", subsection="Шпионский детектив" where genre="det_espionage"; -update genres set section="Документальная литература", subsection="Биографии и Мемуары" where genre="nonf_biography"; -update genres set section="Документальная литература", subsection="Военная документалистика и аналитика" where genre="nonf_military"; -update genres set section="Документальная литература", subsection="Военное дело" where genre="military_special"; -update genres set section="Документальная литература", subsection="География, путевые заметки" where genre="travel_notes"; -update genres set section="Документальная литература", subsection="Документальная литература" where genre="nonfiction"; -update genres set section="Документальная литература", subsection="Публицистика" where genre="nonf_publicism"; -update genres set section="Дом и семья", subsection="Автомобили и ПДД" where genre="auto_regulations"; -update genres set section="Дом и семья", subsection="Боевые искусства, спорт" where genre="home_sport"; -update genres set section="Дом и семья", subsection="Домашние животные" where genre="home_pets"; -update genres set section="Дом и семья", subsection="Домоводство" where genre="home"; -update genres set section="Дом и семья", subsection="Здоровье" where genre="home_health"; -update genres set section="Дом и семья", subsection="Коллекционирование" where genre="home_collecting"; -update genres set section="Дом и семья", subsection="Кулинария" where genre="home_cooking"; -update genres set section="Дом и семья", subsection="Педагогика, воспитание детей, литература для родителей" where genre="sci_pedagogy"; -update genres set section="Дом и семья", subsection="Развлечения" where genre="home_entertain"; -update genres set section="Дом и семья", subsection="Сад и огород" where genre="home_garden"; -update genres set section="Дом и семья", subsection="Сделай сам" where genre="home_diy"; -update genres set section="Дом и семья", subsection="Семейные отношения" where genre="family"; -update genres set section="Дом и семья", subsection="Семейные отношения, секс" where genre="home_sex"; -update genres set section="Дом и семья", subsection="Хобби и ремесла" where genre="home_crafts"; -update genres set section="Драматургия", subsection="Античная драма" where genre="drama_antique"; -update genres set section="Драматургия", subsection="Драма" where genre="drama"; -update genres set section="Драматургия", subsection="Драматургия" where genre="dramaturgy"; -update genres set section="Драматургия", subsection="Комедия" where genre="comedy"; -update genres set section="Драматургия", subsection="Мистерия, буффонада, водевиль" where genre="vaudeville"; -update genres set section="Драматургия", subsection="Сценарий" where genre="screenplays"; -update genres set section="Драматургия", subsection="Трагедия" where genre="tragedy"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Живопись, альбомы, иллюстрированные каталоги" where genre="painting"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Искусство и Дизайн" where genre="design"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Искусствоведение" where genre="art_criticism"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Кино" where genre="cine"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Критика" where genre="nonf_criticism"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Культурология" where genre="sci_culture"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Мировая художественная культура" where genre="art_world_culture"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Музыка" where genre="music"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Партитуры" where genre="notes"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Скульптура и архитектура" where genre="architecture_book"; -update genres set section="Искусство, Искусствоведение, Дизайн", subsection="Театр" where genre="theatre"; -update genres set section="Компьютеры и Интернет", subsection="Зарубежная компьютерная, околокомпьютерная литература" where genre="computers"; -update genres set section="Компьютеры и Интернет", subsection="Компьютерное 'железо'" where genre="comp_hard"; -update genres set section="Компьютеры и Интернет", subsection="ОС и Сети, интернет" where genre="comp_www"; -update genres set section="Компьютеры и Интернет", subsection="Программирование, программы, базы данных" where genre="comp_db"; -update genres set section="Компьютеры и Интернет", subsection="Учебные пособия, самоучители" where genre="tbg_computers"; -update genres set section="Литература для детей", subsection="Детская литература" where genre="children"; -update genres set section="Литература для детей", subsection="Детская образовательная литература" where genre="child_education"; -update genres set section="Литература для детей", subsection="Детская остросюжетная литература" where genre="child_det"; -update genres set section="Литература для детей", subsection="Зарубежная литература для детей" where genre="foreign_children"; -update genres set section="Литература для детей", subsection="Игры, упражнения для детей" where genre="prose_game"; -update genres set section="Литература для детей", subsection="Классическая детская литература" where genre="child_classical"; -update genres set section="Литература для детей", subsection="Проза для детей" where genre="child_prose"; -update genres set section="Литература для детей", subsection="Русские сказки" where genre="child_tale_rus"; -update genres set section="Литература для детей", subsection="Сказки народов мира" where genre="child_tale"; -update genres set section="Литература для детей", subsection="Стихи для детей" where genre="child_verse"; -update genres set section="Литература для детей", subsection="Фантастика для детей" where genre="child_sf"; -update genres set section="Любовные романы", subsection="Исторические любовные романы" where genre="love_history"; -update genres set section="Любовные романы", subsection="Короткие любовные романы" where genre="love_short"; -update genres set section="Любовные романы", subsection="Любовное фэнтези, любовно-фантастические романы" where genre="love_sf"; -update genres set section="Любовные романы", subsection="Любовные романы" where genre="love"; -update genres set section="Любовные романы", subsection="Остросюжетные любовные романы" where genre="love_detective"; -update genres set section="Любовные романы", subsection="Порно" where genre="love_hard"; -update genres set section="Любовные романы", subsection="Современные любовные романы" where genre="love_contemporary"; -update genres set section="Любовные романы", subsection="Эротическая литература" where genre="love_erotica"; -update genres set section="Наука, Образование", subsection="Альтернативная медицина" where genre="sci_medicine_alternative"; -update genres set section="Наука, Образование", subsection="Альтернативные науки и научные теории" where genre="sci_theories"; -update genres set section="Наука, Образование", subsection="Астрономия и Космос" where genre="sci_cosmos"; -update genres set section="Наука, Образование", subsection="Биология, биофизика, биохимия" where genre="sci_biology"; -update genres set section="Наука, Образование", subsection="Ботаника" where genre="sci_botany"; -update genres set section="Наука, Образование", subsection="Ветеринария" where genre="sci_veterinary"; -update genres set section="Наука, Образование", subsection="Военная история" where genre="military_history"; -update genres set section="Наука, Образование", subsection="Востоковедение" where genre="sci_oriental"; -update genres set section="Наука, Образование", subsection="Геология и география" where genre="sci_geo"; -update genres set section="Наука, Образование", subsection="Государство и право" where genre="sci_state"; -update genres set section="Наука, Образование", subsection="Зарубежная образовательная литература, зарубежная прикладная, научно-популярная литература" where genre="sci_popular"; -update genres set section="Наука, Образование", subsection="Зоология" where genre="sci_zoo"; -update genres set section="Наука, Образование", subsection="История" where genre="sci_history"; -update genres set section="Наука, Образование", subsection="Литературоведение" where genre="sci_philology"; -update genres set section="Наука, Образование", subsection="Математика" where genre="sci_math"; -update genres set section="Наука, Образование", subsection="Медицина" where genre="sci_medicine"; -update genres set section="Наука, Образование", subsection="Научная литература" where genre="science"; -update genres set section="Наука, Образование", subsection="Обществознание, социология" where genre="sci_social_studies"; -update genres set section="Наука, Образование", subsection="Политика" where genre="sci_politics"; -update genres set section="Наука, Образование", subsection="Психология и психотерапия" where genre="sci_psychology"; -update genres set section="Наука, Образование", subsection="Физика" where genre="sci_phys"; -update genres set section="Наука, Образование", subsection="Философия" where genre="sci_philosophy"; -update genres set section="Наука, Образование", subsection="Химия" where genre="sci_chem"; -update genres set section="Наука, Образование", subsection="Экология" where genre="sci_ecology"; -update genres set section="Наука, Образование", subsection="Экономика" where genre="sci_economy"; -update genres set section="Наука, Образование", subsection="Юриспруденция" where genre="sci_juris"; -update genres set section="Наука, Образование", subsection="Языкознание, иностранные языки" where genre="sci_linguistic"; -update genres set section="Поэзия", subsection="Визуальная и экспериментальная поэзия, верлибры, палиндромы" where genre="palindromes"; -update genres set section="Поэзия", subsection="Классическая зарубежная поэзия" where genre="poetry_for_classical"; -update genres set section="Поэзия", subsection="Классическая поэзия" where genre="poetry_classical"; -update genres set section="Поэзия", subsection="Классическая русская поэзия" where genre="poetry_rus_classical"; -update genres set section="Поэзия", subsection="Лирика" where genre="lyrics"; -update genres set section="Поэзия", subsection="Песенная поэзия" where genre="song_poetry"; -update genres set section="Поэзия", subsection="Поэзия" where genre="poetry"; -update genres set section="Поэзия", subsection="Поэзия Востока" where genre="poetry_east"; -update genres set section="Поэзия", subsection="Поэма, эпическая поэзия" where genre="poem"; -update genres set section="Поэзия", subsection="Современная зарубежная поэзия" where genre="poetry_for_modern"; -update genres set section="Поэзия", subsection="Современная поэзия" where genre="poetry_modern"; -update genres set section="Поэзия", subsection="Современная русская поэзия" where genre="poetry_rus_modern"; -update genres set section="Поэзия", subsection="Юмористические стихи, басни" where genre="humor_verse"; -update genres set section="Приключения", subsection="Авантюрный роман" where genre="adv_story"; -update genres set section="Приключения", subsection="Вестерн, про индейцев" where genre="adv_indian"; -update genres set section="Приключения", subsection="Исторические приключения" where genre="adv_history"; -update genres set section="Приключения", subsection="Морские приключения" where genre="adv_maritime"; -update genres set section="Приключения", subsection="Приключения" where genre="adventure"; -update genres set section="Приключения", subsection="Приключения в современном мире" where genre="adv_modern"; -update genres set section="Приключения", subsection="Приключения для детей и подростков" where genre="child_adv"; -update genres set section="Приключения", subsection="Природа и животные" where genre="adv_animal"; -update genres set section="Приключения", subsection="Путешествия и география" where genre="adv_geo"; -update genres set section="Приключения", subsection="Рыцарский роман" where genre="tale_chivalry"; -update genres set section="Проза", subsection="Афоризмы, цитаты" where genre="aphorisms"; -update genres set section="Проза", subsection="Готический роман" where genre="gothic_novel"; -update genres set section="Проза", subsection="Зарубежная классическая проза" where genre="foreign_prose"; -update genres set section="Проза", subsection="Историческая проза" where genre="prose_history"; -update genres set section="Проза", subsection="Классическая проза" where genre="prose_classic"; -update genres set section="Проза", subsection="Классическая проза XVII-XVIII веков" where genre="literature_18"; -update genres set section="Проза", subsection="Классическая проза ХIX века" where genre="literature_19"; -update genres set section="Проза", subsection="Классическая проза ХX века" where genre="literature_20"; -update genres set section="Проза", subsection="Контркультура" where genre="prose_counter"; -update genres set section="Проза", subsection="Магический реализм" where genre="prose_magic"; -update genres set section="Проза", subsection="Малые литературные формы прозы: рассказы, эссе, новеллы, феерия" where genre="story"; -update genres set section="Проза", subsection="Проза" where genre="prose"; -update genres set section="Проза", subsection="Проза о войне" where genre="prose_military"; -update genres set section="Проза", subsection="Роман, повесть" where genre="great_story"; -update genres set section="Проза", subsection="Русская классическая проза" where genre="prose_rus_classic"; -update genres set section="Проза", subsection="Советская классическая проза" where genre="prose_su_classics"; -update genres set section="Проза", subsection="Современная русская и зарубежная проза" where genre="prose_contemporary"; -update genres set section="Проза", subsection="Средневековая классическая проза" where genre="foreign_antique"; -update genres set section="Проза", subsection="Фантасмагория, абсурдистская проза" where genre="prose_abs"; -update genres set section="Проза", subsection="Экспериментальная, неформатная проза" where genre="prose_neformatny"; -update genres set section="Проза", subsection="Эпистолярная проза" where genre="epistolary_fiction"; -update genres set section="Прочее", subsection="Журналы, газеты" where genre="periodic"; -update genres set section="Прочее", subsection="Комиксы" where genre="comics"; -update genres set section="Прочее", subsection="Незавершенное" where genre="unfinished"; -update genres set section="Прочее", subsection="Неотсортированное" where genre="other"; -update genres set section="Прочее", subsection="Самиздат, сетевая литература" where genre="network_literature"; -update genres set section="Прочее", subsection="Фанфик" where genre="fanfiction"; -update genres set section="Религия, духовность, эзотерика", subsection="Астрология и хиромантия" where genre="astrology"; -update genres set section="Религия, духовность, эзотерика", subsection="Буддизм" where genre="religion_budda"; -update genres set section="Религия, духовность, эзотерика", subsection="Индуизм" where genre="religion_hinduism"; -update genres set section="Религия, духовность, эзотерика", subsection="Ислам" where genre="religion_islam"; -update genres set section="Религия, духовность, эзотерика", subsection="Иудаизм" where genre="religion_judaism"; -update genres set section="Религия, духовность, эзотерика", subsection="Католицизм" where genre="religion_catholicism"; -update genres set section="Религия, духовность, эзотерика", subsection="Православие" where genre="religion_orthodoxy"; -update genres set section="Религия, духовность, эзотерика", subsection="Протестантизм" where genre="religion_protestantism"; -update genres set section="Религия, духовность, эзотерика", subsection="Религиоведение" where genre="sci_religion"; -update genres set section="Религия, духовность, эзотерика", subsection="Религия, религиозная литература" where genre="religion"; -update genres set section="Религия, духовность, эзотерика", subsection="Самосовершенствование" where genre="religion_self"; -update genres set section="Религия, духовность, эзотерика", subsection="Христианство" where genre="religion_christianity"; -update genres set section="Религия, духовность, эзотерика", subsection="Эзотерика, эзотерическая литература" where genre="religion_esoterics"; -update genres set section="Религия, духовность, эзотерика", subsection="Язычество" where genre="religion_paganism"; -update genres set section="Справочная литература", subsection="Путеводители, карты, атласы" where genre="geo_guides"; -update genres set section="Справочная литература", subsection="Руководства" where genre="ref_guide"; -update genres set section="Справочная литература", subsection="Словари" where genre="ref_dict"; -update genres set section="Справочная литература", subsection="Справочная литература" where genre="reference"; -update genres set section="Справочная литература", subsection="Справочники" where genre="ref_ref"; -update genres set section="Справочная литература", subsection="Энциклопедии" where genre="ref_encyc"; -update genres set section="Старинное", subsection="antique" where genre="antique"; -update genres set section="Старинное", subsection="Античная литература" where genre="antique_ant"; -update genres set section="Старинное", subsection="Древневосточная литература" where genre="antique_east"; -update genres set section="Старинное", subsection="Древнерусская литература" where genre="antique_russian"; -update genres set section="Старинное", subsection="Европейская старинная литература" where genre="antique_european"; -update genres set section="Техника", subsection="Автодело" where genre="auto_business"; -update genres set section="Техника", subsection="Военное дело, военная техника и вооружение" where genre="military_weapon"; -update genres set section="Техника", subsection="История техники" where genre="equ_history"; -update genres set section="Техника", subsection="Металлургия" where genre="sci_metal"; -update genres set section="Техника", subsection="Радиоэлектроника" where genre="sci_radio"; -update genres set section="Техника", subsection="Строительство и сопромат" where genre="sci_build"; -update genres set section="Техника", subsection="Технические науки" where genre="sci_tech"; -update genres set section="Техника", subsection="Транспорт и авиация" where genre="sci_transport"; -update genres set section="Учебники и пособия", subsection="Учебники и пособия" where genre="sci_textbook"; -update genres set section="Учебники и пособия", subsection="Учебники и пособия ВУЗов" where genre="tbg_higher"; -update genres set section="Учебники и пособия", subsection="Учебники и пособия для среднего и специального образования" where genre="tbg_secondary"; -update genres set section="Учебники и пособия", subsection="Школьные учебники и пособия, рефераты, шпаргалки" where genre="tbg_school"; -update genres set section="Фантастика", subsection="Альтернативная история, попаданцы" where genre="sf_history"; -update genres set section="Фантастика", subsection="Боевая фантастика" where genre="sf_action"; -update genres set section="Фантастика", subsection="Героическая фантастика" where genre="sf_heroic"; -update genres set section="Фантастика", subsection="Городское фэнтези" where genre="sf_fantasy_city"; -update genres set section="Фантастика", subsection="Детективная фантастика" where genre="sf_detective"; -update genres set section="Фантастика", subsection="Киберпанк" where genre="sf_cyberpunk"; -update genres set section="Фантастика", subsection="Космическая фантастика" where genre="sf_space"; -update genres set section="Фантастика", subsection="Мистика" where genre="sf_mystic"; -update genres set section="Фантастика", subsection="Мифологическое фэнтези" where genre="fairy_fantasy"; -update genres set section="Фантастика", subsection="Научная Фантастика" where genre="sf"; -update genres set section="Фантастика", subsection="Постапокалипсис" where genre="sf_postapocalyptic"; -update genres set section="Фантастика", subsection="Славянское фэнтези" where genre="russian_fantasy"; -update genres set section="Фантастика", subsection="Современная сказка" where genre="modern_tale"; -update genres set section="Фантастика", subsection="Социально-психологическая фантастика" where genre="sf_social"; -update genres set section="Фантастика", subsection="Стимпанк" where genre="sf_stimpank"; -update genres set section="Фантастика", subsection="Технофэнтези" where genre="sf_technofantasy"; -update genres set section="Фантастика", subsection="Ужасы" where genre="sf_horror"; -update genres set section="Фантастика", subsection="Фантастика" where genre="sf_etc"; -update genres set section="Фантастика", subsection="Фэнтези" where genre="sf_fantasy"; -update genres set section="Фантастика", subsection="Хроноопера" where genre="hronoopera"; -update genres set section="Фантастика", subsection="Эпическая фантастика" where genre="sf_epic"; -update genres set section="Фантастика", subsection="Юмористическая фантастика" where genre="sf_humor"; -update genres set section="Фольклор", subsection="Былины, эпопея" where genre="epic"; -update genres set section="Фольклор", subsection="Детский фольклор" where genre="child_folklore"; -update genres set section="Фольклор", subsection="Мифы. Легенды. Эпос" where genre="antique_myths"; -update genres set section="Фольклор", subsection="Народные песни" where genre="folk_songs"; -update genres set section="Фольклор", subsection="Народные сказки" where genre="folk_tale"; -update genres set section="Фольклор", subsection="Пословицы, поговорки" where genre="proverbs"; -update genres set section="Фольклор", subsection="Фольклор, загадки folklore" where genre="folklore"; -update genres set section="Фольклор", subsection="Частушки, прибаутки, потешки" where genre="limerick"; -update genres set section="Юмор", subsection="Анекдоты" where genre="humor_anecdote"; -update genres set section="Юмор", subsection="Сатира" where genre="humor_satire"; -update genres set section="Юмор", subsection="Юмор" where genre="humor"; -update genres set section="Юмор", subsection="Юмористическая проза" where genre="humor_prose"; -commit; diff --git a/db/tables.sql b/db/tables.sql deleted file mode 100644 index ba114064c234eeed443e538dd906392712512036..0000000000000000000000000000000000000000 --- a/db/tables.sql +++ /dev/null @@ -1,207 +0,0 @@ -SET NAMES 'utf8'; -SET CHARACTER SET utf8; - -drop table if exists books; -create table books ( -book_id INT not null AUTO_INCREMENT, -filename VARCHAR(256), -path VARCHAR(1024), -filesize INT not null DEFAULT 0, -format VARCHAR(8), -cat_id INT not null, -cat_type INT not null DEFAULT 0, -registerdate TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP, -docdate VARCHAR(20), -favorite INT not null DEFAULT 0, -lang VARCHAR(16), -title VARCHAR(256), -annotation VARCHAR(10000), -cover VARCHAR(32), -cover_type VARCHAR(32), -doublicat INT not null DEFAULT 0, -avail INT not null DEFAULT 0, -PRIMARY KEY(book_id), -KEY(filename), -KEY(title,format,filesize), -INDEX(path), -INDEX(cat_id), -INDEX(avail,doublicat), -INDEX(registerdate)); -commit; - -drop table if exists catalogs; -create table catalogs ( -cat_id INT not null AUTO_INCREMENT, -parent_id INT null, -cat_name VARCHAR(64), -path VARCHAR(1024), -cat_type INT not null DEFAULT 0, -PRIMARY KEY(cat_id), -KEY(cat_name,path(256))); -commit; - -drop table if exists authors; -create table authors ( -author_id INT not null AUTO_INCREMENT, -first_name VARCHAR(64), -last_name VARCHAR(64), -PRIMARY KEY(author_id), -KEY(last_name,first_name)); -commit; - -drop table if exists bauthors; -create table bauthors ( -author_id INT not NULL, -book_id INT not NULL, -PRIMARY KEY(book_id,author_id), -INDEX(author_id)); -commit; - -drop table if exists genres; -create table genres( -genre_id INT not null AUTO_INCREMENT, -genre VARCHAR(32), -section VARCHAR(64), -subsection VARCHAR(100), -PRIMARY KEY(genre_id), -KEY(genre)); -commit; - -drop table if exists bgenres; -create table bgenres( -genre_id INT not NULL, -book_id INT not NULL, -PRIMARY KEY(book_id,genre_id), -INDEX(genre_id)); -commit; - -drop table if exists series; -create table series( -ser_id INT not null AUTO_INCREMENT, -ser VARCHAR(64), -PRIMARY KEY(ser_id), -KEY(ser)); -commit; - -drop table if exists bseries; -create table bseries( -ser_id INT not NULL, -book_id INT not NULL, -ser_no TINYINT UNSIGNED NOT NULL DEFAULT 0, -PRIMARY KEY(book_id,ser_id), -INDEX(ser_id)); -commit; - -drop table if exists bookshelf; -create table bookshelf( -user VARCHAR(32) not NULL, -book_id INT not NULL, -readtime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -INDEX(user,readtime)); -commit; - -drop table if exists dbver; -create table dbver( -ver varchar(5)); -commit; - -insert into dbver(ver) values("0.21"); -commit; -insert into authors(author_id,last_name,first_name) values(1,"Неизвестный Автор",""); -commit; - -DROP PROCEDURE IF EXISTS sp_update_dbl; -DROP PROCEDURE IF EXISTS sp_newinfo; -DROP FUNCTION IF EXISTS BOOK_CMPSTR; -DROP PROCEDURE IF EXISTS sp_mark_dbl; -DELIMITER // - -CREATE FUNCTION BOOK_CMPSTR(id INT, cmp_type INT) -RETURNS VARCHAR(512) -BEGIN - DECLARE done INT DEFAULT 0; - DECLARE T VARCHAR(256); - DECLARE fmt VARCHAR(8) DEFAULT ''; - DECLARE fsize INT DEFAULT 0; - DECLARE AUTHORS VARCHAR(256) DEFAULT ''; - DECLARE RESULT VARCHAR(512); - SELECT GROUP_CONCAT(DISTINCT author_id order by author_id SEPARATOR ':') into AUTHORS from bauthors where book_id=id; - IF AUTHORS=NULL THEN - SET AUTHORS=''; - END IF; - - SELECT UPPER(trim(REPLACE(title,' ',''))),format,filesize INTO T,fmt,fsize FROM books WHERE book_id=id; - IF T=NULL THEN - SET T=''; - END IF; - - IF cmp_type=1 THEN - SET RESULT=CONCAT_WS(':',T,AUTHORS); - ELSEIF cmp_type=2 THEN - SET RESULT=CONCAT_WS(':',T,fsize,fmt); - ELSE - SET RESULT=''; - END IF; - - RETURN RESULT; -END // - -CREATE PROCEDURE sp_mark_dbl(cmp_type INT) -BEGIN - DECLARE done INT DEFAULT 0; - DECLARE idx,prev,current,orig_id INT; - DECLARE ids VARCHAR(512); - DECLARE cur CURSOR for select GROUP_CONCAT(DISTINCT book_id order by filesize DESC SEPARATOR ':') as ids - from books where avail<>0 group by BOOK_CMPSTR(book_id,cmp_type) having SUM(IF(doublicat=0,1,0))<>1; - DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; - - IF cmp_type=1 or cmp_type=2 THEN - OPEN cur; - - WHILE done=0 DO - FETCH cur INTO ids; - IF done=0 THEN - set idx=0; - set prev=-1; - set current=0; - set orig_id=0; - WHILE prev<>current DO - set prev=current; - set idx=idx+1; - SELECT CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(ids,':',idx),':',-1) as UNSIGNED) into current; - IF prev<>current THEN - UPDATE books SET doublicat=orig_id where book_id=current; - if orig_id=0 THEN SET orig_id=current; END IF; - END IF; - END WHILE; - END IF; - END WHILE; - CLOSE cur; - END IF; - - IF cmp_type=3 THEN - UPDATE books SET doublicat=0; - END IF; - -END // - -CREATE PROCEDURE sp_newinfo(period INT) -BEGIN - DECLARE min_book_id INT; - - select MIN(book_id) into min_book_id from books where registerdate>now()-INTERVAL period DAY; - select 1 s, count(*) from books where book_id>=min_book_id and avail!=0 and doublicat=0 - union all - select 2 s, count(*) from (select author_id from bauthors where book_id>=min_book_id group by author_id) a - union all - select 3 s, count(*) from (select genre_id from bgenres where book_id>=min_book_id group by genre_id) a - union all - select 4 s, count(*) from (select ser_id from bseries where book_id>=min_book_id group by ser_id) a - order by s; - -END // - - -DELIMITER ; -commit; - diff --git a/db/updates/update014-015.sql b/db/updates/update014-015.sql deleted file mode 100644 index 51111a427035872d3a3394fc16728ff6dc9ba0e1..0000000000000000000000000000000000000000 --- a/db/updates/update014-015.sql +++ /dev/null @@ -1,33 +0,0 @@ -update dbver set ver="0.15"; -update authors set first_name="" where author_id=1; - -drop table if exists bookshelf; -create table bookshelf( -user VARCHAR(32) not NULL, -book_id INT not NULL, -readtime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -INDEX(user,readtime)); -commit; - -DROP PROCEDURE IF EXISTS sp_newinfo; - -DELIMITER // - -CREATE PROCEDURE sp_newinfo(period INT) -BEGIN - DECLARE min_book_id INT; - - select MIN(book_id) into min_book_id from books where registerdate>now()-INTERVAL period DAY; - select 1 s, count(*) from books where book_id>=min_book_id and avail!=0 and doublicat=0 - union all - select 2 s, count(*) from (select author_id from bauthors where book_id>=min_book_id group by author_id) a - union all - select 3 s, count(*) from (select genre_id from bgenres where book_id>=min_book_id group by genre_id) a - union all - select 4 s, count(*) from (select ser_id from bseries where book_id>=min_book_id group by ser_id) a - order by s; -END // - -DELIMITER ; -commit; - diff --git a/db/updates/update015-018.sql b/db/updates/update015-018.sql deleted file mode 100644 index b352434d6002e1897beb2585709028e6fb0635a2..0000000000000000000000000000000000000000 --- a/db/updates/update015-018.sql +++ /dev/null @@ -1,6 +0,0 @@ -update dbver set ver="0.18"; -create index idx_path on books(path(256)); -create index idx_cat0 on catalogs(cat_name,path(256)); -create index idx_books_catid on books(cat_id); -commit; - diff --git a/db/updates/update020-021.sql b/db/updates/update020-021.sql deleted file mode 100644 index 73006006955c61f0c18587077863c42df02cbc05..0000000000000000000000000000000000000000 --- a/db/updates/update020-021.sql +++ /dev/null @@ -1,80 +0,0 @@ -update dbver set ver="0.21"; -DROP PROCEDURE IF EXISTS sp_update_dbl; -DROP FUNCTION IF EXISTS BOOK_CMPSTR; -DROP PROCEDURE IF EXISTS sp_mark_dbl; -DELIMITER // - -CREATE FUNCTION BOOK_CMPSTR(id INT, cmp_type INT) -RETURNS VARCHAR(512) -BEGIN - DECLARE done INT DEFAULT 0; - DECLARE T VARCHAR(256); - DECLARE fmt VARCHAR(8) DEFAULT ''; - DECLARE fsize INT DEFAULT 0; - DECLARE AUTHORS VARCHAR(256) DEFAULT ''; - DECLARE RESULT VARCHAR(512); - SELECT GROUP_CONCAT(DISTINCT author_id order by author_id SEPARATOR ':') into AUTHORS from bauthors where book_id=id; - IF AUTHORS=NULL THEN - SET AUTHORS=''; - END IF; - - SELECT UPPER(trim(REPLACE(title,' ',''))),format,filesize INTO T,fmt,fsize FROM books WHERE book_id=id; - IF T=NULL THEN - SET T=''; - END IF; - - IF cmp_type=1 THEN - SET RESULT=CONCAT_WS(':',T,AUTHORS); - ELSEIF cmp_type=2 THEN - SET RESULT=CONCAT_WS(':',T,fsize,fmt); - ELSE - SET RESULT=''; - END IF; - - RETURN RESULT; -END // - -CREATE PROCEDURE sp_mark_dbl(cmp_type INT) -BEGIN - DECLARE done INT DEFAULT 0; - DECLARE idx,prev,current,orig_id INT; - DECLARE ids VARCHAR(512); - DECLARE cur CURSOR for select GROUP_CONCAT(DISTINCT book_id order by filesize DESC SEPARATOR ':') as ids - from books where avail<>0 group by BOOK_CMPSTR(book_id,cmp_type) having SUM(IF(doublicat=0,1,0))<>1; - DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; - - IF cmp_type=1 or cmp_type=2 THEN - OPEN cur; - - WHILE done=0 DO - FETCH cur INTO ids; - IF done=0 THEN - set idx=0; - set prev=-1; - set current=0; - set orig_id=0; - WHILE prev<>current DO - set prev=current; - set idx=idx+1; - SELECT CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(ids,':',idx),':',-1) as UNSIGNED) into current; - IF prev<>current THEN - UPDATE books SET doublicat=orig_id where book_id=current; - if orig_id=0 THEN SET orig_id=current; END IF; - END IF; - END WHILE; - END IF; - END WHILE; - CLOSE cur; - END IF; - - IF cmp_type=3 THEN - UPDATE books SET doublicat=0; - END IF; - -END // - -DELIMITER ; -commit; - - - diff --git a/db/updates/update021-0211.sql b/db/updates/update021-0211.sql deleted file mode 100644 index 29a643cc53e6c3876ed2c1b466b152e96c01d5f8..0000000000000000000000000000000000000000 --- a/db/updates/update021-0211.sql +++ /dev/null @@ -1,5 +0,0 @@ -update dbver set ver="0.211"; -alter table genres modify section VARCHAR(64), modify subsection VARCHAR(100); -\. ../genresupd.sql -commit; - diff --git a/logs/.gitignore b/logs/.gitignore deleted file mode 100644 index 397b4a7624e35fa60563a9c03b1213d93f7b6546..0000000000000000000000000000000000000000 --- a/logs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.log diff --git a/manage.py b/manage.py new file mode 100644 index 0000000000000000000000000000000000000000..71f357175654aac55b666b856ed6f4802ec04992 --- /dev/null +++ b/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sopds.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/opds_catalog/__init__.py b/opds_catalog/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opds_catalog/__pycache__/__init__.cpython-35.pyc b/opds_catalog/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57bae3343907c267477dfd71cda10aa217aa0f5c Binary files /dev/null and b/opds_catalog/__pycache__/__init__.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/admin.cpython-35.pyc b/opds_catalog/__pycache__/admin.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e4611efe7c24047cfe93f30138498d4321e56aa Binary files /dev/null and b/opds_catalog/__pycache__/admin.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/dl.cpython-35.pyc b/opds_catalog/__pycache__/dl.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..afc93fcb3da110724cec7a9ad405a0954ae66ab5 Binary files /dev/null and b/opds_catalog/__pycache__/dl.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/fb2parse.cpython-35.pyc b/opds_catalog/__pycache__/fb2parse.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..934e6cd4df3000467b72949dd5327b8d74de6c5b Binary files /dev/null and b/opds_catalog/__pycache__/fb2parse.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/feeds.cpython-35.pyc b/opds_catalog/__pycache__/feeds.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de58128d065f4672e3df85fbb37d1dfeb4bb8c56 Binary files /dev/null and b/opds_catalog/__pycache__/feeds.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/models.cpython-35.pyc b/opds_catalog/__pycache__/models.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4430318aa5590959aa1fdbddb77817f4797bfa7c Binary files /dev/null and b/opds_catalog/__pycache__/models.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/opds_middleware.cpython-35.pyc b/opds_catalog/__pycache__/opds_middleware.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebab18e4fddd6badfc0c01a6c372081f68e03347 Binary files /dev/null and b/opds_catalog/__pycache__/opds_middleware.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/opdsdb.cpython-35.pyc b/opds_catalog/__pycache__/opdsdb.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02629b80cb079fce126cfa619b6676042f6d3ebd Binary files /dev/null and b/opds_catalog/__pycache__/opdsdb.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/settings.cpython-35.pyc b/opds_catalog/__pycache__/settings.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ef378f60623e6be9cc0eab37ec9d080c5b47b93 Binary files /dev/null and b/opds_catalog/__pycache__/settings.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/sopdscan.cpython-35.pyc b/opds_catalog/__pycache__/sopdscan.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d440ab79a6457d7b9de4d505a53a6c998c23e6d0 Binary files /dev/null and b/opds_catalog/__pycache__/sopdscan.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/urls.cpython-35.pyc b/opds_catalog/__pycache__/urls.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0cb2b64a957c3ac62936ddb7b51f09961ea8e7a2 Binary files /dev/null and b/opds_catalog/__pycache__/urls.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/utils.cpython-35.pyc b/opds_catalog/__pycache__/utils.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..25e9b0728fdb0414a837afaff277bc163c034d3f Binary files /dev/null and b/opds_catalog/__pycache__/utils.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/views.cpython-35.pyc b/opds_catalog/__pycache__/views.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b0ec361bbc55c0000f0fedca51c139310bc4be9 Binary files /dev/null and b/opds_catalog/__pycache__/views.cpython-35.pyc differ diff --git a/opds_catalog/__pycache__/zipf.cpython-35.pyc b/opds_catalog/__pycache__/zipf.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2627572f8aa7d54f5f13cf5dffb58d0528852902 Binary files /dev/null and b/opds_catalog/__pycache__/zipf.cpython-35.pyc differ diff --git a/opds_catalog/admin.py b/opds_catalog/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..201ea1884d5c94ffc8e2bfd42f6d42538584fb74 --- /dev/null +++ b/opds_catalog/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from opds_catalog.models import Genre + +# Register your models here. +class Genre_admin(admin.ModelAdmin): + list_display = ('genre', 'section', 'subsection') + +admin.site.register(Genre, Genre_admin) diff --git a/opds_catalog/apps.py b/opds_catalog/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..df113652b1159c9b261ac0216fad874b43bd7749 --- /dev/null +++ b/opds_catalog/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class OpdsCatalogConfig(AppConfig): + name = 'opds_catalog' diff --git a/opds_catalog/dl.py b/opds_catalog/dl.py new file mode 100644 index 0000000000000000000000000000000000000000..3611d3e6ce1c1cc35e91c4e2d2910fb2c4ce3319 --- /dev/null +++ b/opds_catalog/dl.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- + +import os +import codecs +import base64 +import io +import subprocess + +from django.http import HttpResponse, Http404 + +from opds_catalog.models import Book, bookshelf +from opds_catalog import settings, utils, opdsdb, fb2parse +import opds_catalog.zipf as zipfile + +def Download(request, book_id, zip_flag): + """ Загрузка файла книги """ + book = Book.objects.get(id=book_id) + + if settings.AUTH: + bookshelf.objects.get_or_create(user=request.user, book=book) + + full_path=os.path.join(settings.ROOT_LIB,book.path) + if settings.TITLE_AS_FILENAME: + transname=utils.translit(book.title+'.'+book.format) + else: + transname=utils.translit(book.filename) + + if zip_flag=='1': + dlfilename=transname+'.zip' + content_type='application/zip' + else: + dlfilename=transname + if book.format=="fb2": + content_type='text/xml' + elif book.format=="epub": + content_type='application/epub+zip' + elif book.format=="mobi": + content_type='application/x-mobipocket-ebook' + else: + content_type='application/octet-stream' + + response = HttpResponse() + response["Content-Type"]='%s; name="%s"'%(content_type,dlfilename) + response["Content-Disposition"] = 'attachment; filename="%s"'%(dlfilename) + response["Content-Transfer-Encoding"]='binary' + + z = None + fz = None + s = None + book_size = book.filesize + if book.cat_type==opdsdb.CAT_NORMAL: + file_path=os.path.join(full_path, book.filename) + book_size=os.path.getsize(file_path) + fo=codecs.open(file_path, "rb") + s=fo.read() + elif book.cat_type==opdsdb.CAT_ZIP: + fz=codecs.open(full_path, "rb") + z = zipfile.ZipFile(fz, 'r', allowZip64=True) + book_size=z.getinfo(book.filename).file_size + fo= z.open(book.filename) + s=fo.read() + + if zip_flag=='1': + dio = io.BytesIO() + zo = zipfile.ZipFile(dio, 'w', zipfile.ZIP_DEFLATED) + zo.writestr(transname,s) + zo.close() + buf = dio.getvalue() + response["Content-Length"] = str(len(buf)) + response.write(buf) + else: + response["Content-Length"] = str(book_size) + response.write(s) + + fo.close() + if z: z.close() + if fz: fz.close() + + return response + +def Cover(request, book_id): + """ Загрузка обложки """ + book = Book.objects.get(id=book_id) + response = HttpResponse() + c0=0 + if book.format=='fb2': + full_path=os.path.join(settings.ROOT_LIB,book.path) + fb2=fb2parse.fb2parser(1) + if book.cat_type==opdsdb.CAT_NORMAL: + file_path=os.path.join(full_path,book.filename) + fo=codecs.open(file_path, "rb") + fb2.parse(fo,0) + fo.close() + elif book.cat_type==opdsdb.CAT_ZIP: + fz=codecs.open(full_path, "rb") + z = zipfile.ZipFile(fz, 'r', allowZip64=True) + fo = z.open(book.filename) + fb2.parse(fo,0) + fo.close() + z.close() + fz.close() + + if len(fb2.cover_image.cover_data)>0: + try: + s=fb2.cover_image.cover_data + dstr=base64.b64decode(s) + response["Content-Type"]=fb2.cover_image.getattr('content-type') + response.write(dstr) + c0=1 + except: + c0=0 + + if c0==0: + if os.path.exists(settings.NOCOVER_PATH): + response["Content-Type"]='image/jpeg' + f=open(settings.NOCOVER_PATH,"rb") + response.write(f.read()) + f.close() + else: + raise Http404 + + return response + +def ConvertFB2(request, book_id, convert_type): + """ Выдача файла книги после конвертации в EPUB или mobi """ + book = Book.objects.get(id=book_id) + + if book.format!='fb2': + raise Http404 + + if settings.AUTH: + bookshelf.objects.get_or_create(user=request.user, book=book) + + full_path=os.path.join(settings.ROOT_LIB,book.path) + if settings.TITLE_AS_FILENAME: + transname=utils.translit(book.title+'.'+book.format) + else: + transname=utils.translit(book.filename) + (n,e)=os.path.splitext(transname) + dlfilename="%s.%s"%(n,convert_type) + + if convert_type=='epub': + converter_path=settings.FB2TOEPUB + content_type='application/epub+zip' + elif convert_type=='mobi': + converter_path=settings.FB2TOMOBI + content_type='application/x-mobipocket-ebook' + else: + content_type='application/octet-stream' + + if book.cat_type==opdsdb.CAT_NORMAL: + tmp_fb2_path=None + file_path=os.path.join(full_path, book.filename) + elif book.cat_type==opdsdb.CAT_ZIP: + fz=codecs.open(full_path, "rb") + z = zipfile.ZipFile(fz, 'r', allowZip64=True) + z.extract(book.filename,settings.TEMP_DIR) + tmp_fb2_path=os.path.join(settings.TEMP_DIR,book.filename) + file_path=tmp_fb2_path + + tmp_conv_path=os.path.join(settings.TEMP_DIR,dlfilename) + popen_args = ("\"%s\" \"%s\" \"%s\""%(converter_path,file_path,tmp_conv_path)) + proc = subprocess.Popen(popen_args, shell=True, stdout=subprocess.PIPE) + #proc = subprocess.Popen((converter_path.encode('utf8'),file_path.encode('utf8'),tmp_conv_path.encode('utf8')), shell=True, stdout=subprocess.PIPE) + out = proc.stdout.readlines() + + if os.path.isfile(tmp_conv_path): + fo=codecs.open(tmp_conv_path, "rb") + s=fo.read() + # HTTP Header + response = HttpResponse() + response["Content-Type"]='%s; name="%s"'%(content_type,dlfilename) + response["Content-Disposition"] = 'attachment; filename="%s"'%(dlfilename) + response["Content-Transfer-Encoding"]='binary' + response["Content-Length"] = str(len(s)) + response.write(s) + fo.close() + else: + raise Http404 + + try: + if tmp_fb2_path: + os.remove(tmp_fb2_path) + except: + pass + try: + os.remove(tmp_conv_path) + except: + pass + + return response \ No newline at end of file diff --git a/py/sopdsparse.py b/opds_catalog/fb2parse.py similarity index 99% rename from py/sopdsparse.py rename to opds_catalog/fb2parse.py index c86e192d1048b700f515d9703c6d27f648e3c5ad..7281909ba25f05f8b74eefb41cc14a47dab23391 100644 --- a/py/sopdsparse.py +++ b/opds_catalog/fb2parse.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - import xml.parsers.expat class fb2tag: diff --git a/opds_catalog/feeds.py b/opds_catalog/feeds.py new file mode 100644 index 0000000000000000000000000000000000000000..41e16c55773b0720992f6a193db941300565292f --- /dev/null +++ b/opds_catalog/feeds.py @@ -0,0 +1,973 @@ +from itertools import chain + +from django.utils import timezone +from django.utils.translation import ugettext as _ +from django.utils.feedgenerator import Atom1Feed, Enclosure, rfc3339_date +from django.contrib.syndication.views import Feed +from django.core.urlresolvers import reverse +from django.core.paginator import Paginator, EmptyPage +from django.shortcuts import render +#from django.core.exceptions import ObjectDoesNotExist +#from django.db.models.functions import Substr, Upper +from django.db.models import Count, Min, Sum +#from django.utils.encoding import escape_uri_path + +from opds_catalog.models import Book, Catalog, Author, Genre, Series, bookshelf, Counter, lang_menu +from opds_catalog import models +from opds_catalog import settings +#from django.http.response import Http404 + +class AuthFeed(Feed): + request = None + def __call__(self,request,*args,**kwargs): + self.request = request + return super().__call__(request,*args,**kwargs) + +class opdsEnclosure(Enclosure): + def __init__(self, url, mime_type, rel): + self.rel = rel + super(opdsEnclosure,self).__init__(url, 0, mime_type) + +class opdsFeed(Atom1Feed): + content_type = 'text/xml; charset=utf-8' + + def root_attributes(self): + attrs = {} + #attrs = super(opdsFeed, self).root_attributes() + attrs['xmlns'] = 'http://www.w3.org/2005/Atom' + attrs['xmlns:dcterms'] = 'http://purl.org/dc/terms' + #attrs['xmlns:os'] = "http://a9.com/-/spec/opensearch/1.1/" + #attrs['xmlns:opds'] = "http://opds-spec.org/2010/catalog" + return attrs + + def add_root_elements(self, handler): + handler._short_empty_elements = True + #super(opdsFeed, self).add_root_elements(handler) + handler.characters("\n") + handler.addQuickElement("id", self.feed['id']) + handler.addQuickElement('icon', settings.ICON) + handler.characters("\n") + if self.feed.get('link') is not None: + handler.addQuickElement('link', None, {"href":self.feed["link"],"rel":"self","type":"application/atom+xml;profile=opds-catalog;kind=navigation"}) + handler.characters("\n") + if self.feed.get('start_url') is not None: + handler.addQuickElement('link', None, {"href":self.feed["start_url"],"rel":"start","type":"application/atom+xml;profile=opds-catalog;kind=navigation"}) + handler.characters("\n") + handler.addQuickElement("title", self.feed['title']) + handler.characters("\n") + if self.feed.get('subtitle') is not None: + handler.addQuickElement("subtitle", self.feed['subtitle']) + handler.characters("\n") + handler.addQuickElement("updated", rfc3339_date(self.latest_post_date())) + handler.characters("\n") + if self.feed.get('prev_url') is not None: + handler.addQuickElement('link', None, {"href":self.feed["prev_url"],"rel":"prev","title":"Previous Page","type":"application/atom+xml;profile=opds-catalog"}) + handler.characters("\n") + if self.feed.get('next_url') is not None: + handler.addQuickElement('link', None, {"href":self.feed["next_url"],"rel":"next","title":"Next Page","type":"application/atom+xml;profile=opds-catalog"}) + handler.characters("\n") + if self.feed.get('search_url') is not None: + handler.addQuickElement('link', None, {"href":self.feed["search_url"],"rel":"search","type":"application/atom+xml;profile=opds-catalog;kind=navigation"}) + handler.characters("\n") + if self.feed.get('searchTerm_url') is not None: + handler.addQuickElement('link', None, {"href":self.feed["searchTerm_url"],"rel":"search","type":"application/atom+xml"}) + handler.characters("\n") + + + def add_item_elements(self, handler, item): + disable_item_links = item.get('disable_item_links') + handler.characters("\n") + handler.addQuickElement("id", item['unique_id']) + handler.characters("\n") + handler.addQuickElement("title", item['title']) + handler.characters("\n") + if not disable_item_links: + handler.addQuickElement("link", "", {"href": item['link'], "rel": "alternate"}) + handler.characters("\n") + # Enclosures. + if not disable_item_links: + if item.get('enclosures') is not None: + for enclosure in item['enclosures']: + handler.addQuickElement('link', '', { + 'rel': enclosure.rel, + 'href': enclosure.url, + 'type': enclosure.mime_type, + }) + handler.characters("\n") + + if item.get('updateddate') is not None: + handler.addQuickElement('updated', rfc3339_date(item['updateddate'])) + handler.characters("\n") + + if self.feed.get("description_mime_type") is not None: + content_type = self.feed["description_mime_type"] + else: + content_type = "text/html" + if item.get("description") is not None: + handler.addQuickElement("content", item["description"], {"type": content_type}) + handler.characters("\n") + + if item.get("authors") is not None: + for a in item["authors"]: + handler.startElement("author", {}) + handler.addQuickElement("name", "%s %s"%(a['last_name'],a['first_name'])) + #handler.addQuickElement("uri", item['author_link']) + handler.endElement("author") + handler.addQuickElement("link", "", {"href": reverse("opds_catalog:searchbooks", kwargs={"searchtype":'a', "searchterms":a['id']}), + "rel": "related", + "type":"application/atom+xml;profile=opds-catalog", + "title":_("All books by %(last_name)s %(first_name)s")%{"last_name":a['last_name'],"first_name":a['first_name']}}) + handler.characters("\n") + + if item.get("genres") is not None: + for g in item["genres"]: + handler.addQuickElement("category", "", {"term": g['subsection'], "label": g['subsection']}) + handler.characters("\n") + + if item.get("doubles") is not None: + handler.addQuickElement("link", "", {"href": reverse("opds_catalog:searchbooks", kwargs={"searchtype":'d', "searchterms":item['doubles']}), + "rel": "related", + "type":"application/atom+xml;profile=opds-catalog", + "title":_("Book doublicates")}) + handler.characters("\n") + + +class MainFeed(AuthFeed): + feed_type = opdsFeed + title = settings.TITLE + subtitle = settings.SUBTITLE + + def link(self): + return reverse("opds_catalog:main") + + def feed_extra_kwargs(self, obj): + return { + "searchTerm_url":"/opds/search/{searchTerms}/", + #"searchTerm_url":reverse("opds_catalog:searchtypes",kwargs={"searchterms":"{searchTerms}"}), + "start_url":reverse("opds_catalog:main"), + "description_mime_type":"text", + } + + def items(self): + mainitems = [ + {"id":1, "title":_("By catalogs"), "link":"opds_catalog:catalogs", + "descr": _("Catalogs: %(catalogs)s, books: %(books)s."),"counters":{"catalogs":Counter.objects.get_counter(models.counter_allcatalogs),"books":Counter.objects.get_counter(models.counter_allbooks)}}, + {"id":2, "title":_("By authors"), "link":("opds_catalog:lang_authors" if settings.ALPHABET_MENU else "opds_catalog:nolang_authors"), + "descr": _("Authors: %(authors)s."),"counters":{"authors":Counter.objects.get_counter(models.counter_allauthors)}}, + {"id":3, "title":_("By titles"), "link":("opds_catalog:lang_books" if settings.ALPHABET_MENU else "opds_catalog:nolang_books"), + "descr": _("Books: %(books)s."),"counters":{"books":Counter.objects.get_counter(models.counter_allbooks)}}, + {"id":4, "title":_("By genres"), "link":"opds_catalog:genres", + "descr": _("Genres: %(genres)s."),"counters":{"genres":Counter.objects.get_counter(models.counter_allgenres)}}, + {"id":5, "title":_("By series"), "link":("opds_catalog:lang_series" if settings.ALPHABET_MENU else "opds_catalog:nolang_series"), + "descr": _("Series: %(series)s."),"counters":{"series":Counter.objects.get_counter(models.counter_allseries)}}, + ] + if settings.AUTH and self.request.user.is_authenticated(): + mainitems += [ + {"id":6, "title":_("%(username)s Book shelf")%({"username":self.request.user.username}), "link":"opds_catalog:bookshelf", + "descr":_("%(username)s books readed: %(bookshelf)s."),"counters":{"bookshelf":bookshelf.objects.filter(user=self.request.user).count(),"username":self.request.user.username}}, + ] + + return mainitems + + def item_link(self, item): + return reverse(item['link']) + + def item_title(self, item): + return item['title'] + + def item_description(self, item): + return item['descr']%item['counters'] + + def item_guid(self, item): + return "m:%s"%item["id"] + + def item_updateddate(self): + return timezone.now() + + def item_enclosures(self, item): + return (opdsEnclosure(reverse(item['link']),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) + + def item_extra_kwargs(self, item): + disable_item_links = (list(item['counters'].values())[0]==0) + return {'disable_item_links':disable_item_links} + +class CatalogsFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + description_template = "book_description_cat.html" + + def get_object(self, request, cat_id=None, page=1): + if not isinstance(page, int): + page = int(page) + + if cat_id is not None: + return (Catalog.objects.get(id=cat_id), page) + else: + return (Catalog.objects.get(parent__id=cat_id), page) + + def title(self, obj): + cat, current_page = obj + if cat.parent: + return "%s | %s | %s"%(settings.TITLE,_("By catalogs"), cat.path) + else: + return "%s | %s"%(settings.TITLE,_("By catalogs")) + + def link(self, obj): + cat, current_page = obj + return reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id, "page":current_page}) + + def feed_extra_kwargs(self, obj): + cat, current_page = obj + start_url = reverse("opds_catalog:main") + if current_page != 1: + prev_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":(current_page-1)}) + else: + prev_url = None + + if current_page*settings.MAXITEMS999 therow error "too many SQL variables" + #books_list = Book.objects.filter(catalog=cat).prefetch_related('authors','genres','series').order_by("title") + books_list = Book.objects.filter(catalog=cat).order_by("title") + union_list = list(chain(catalogs_list,books_list)) + paginator = Paginator(union_list,settings.MAXITEMS) + try: + page = paginator.page(current_page) + except EmptyPage: + page = paginator.page(paginator.num_pages) + + return page + + def item_title(self, item): + if isinstance(item, Catalog): + return item.cat_name + else: + return item.title + + def item_guid(self, item): + if isinstance(item, Catalog): + gp = 'c:' + else: + gp = 'b:' + return "%s%s"%(gp,item.id) + + def item_link(self, item): + if isinstance(item, Catalog): + return reverse("opds_catalog:cat_tree", kwargs={"cat_id":item.id}) + else: + return reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":0}) + + def item_enclosures(self, item): + if isinstance(item, Catalog): + return (opdsEnclosure(reverse("opds_catalog:cat_tree", kwargs={"cat_id":item.id}),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) + else: + return ( + opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":0}),"application/fb2" ,"http://opds-spec.org/acquisition/open-access"), + opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":1}),"application/fb2+zip", "http://opds-spec.org/acquisition/open-access"), + opdsEnclosure(reverse("opds_catalog:cover", kwargs={"book_id":item.id}),"image/jpeg", "http://opds-spec.org/image"), + ) + +def OpenSearch(request): + """ + Выводим шаблон поиска + """ + return render(request, 'opensearch.html') + +class SearchTypesFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + + def get_object(self, request, searchterms=""): + return searchterms + + def link(self, obj): + return "/opds/search/{searchTerms}/" + + def feed_extra_kwargs(self, obj): + return { + "searchTerm_url":"/opds/search/{searchTerms}/", + "start_url":reverse("opds_catalog:main"), + "description_mime_type":"text", + } + + def items(self, obj): + return [ + {"id":1, "title":_("Search by titles"), "term":obj, "descr": _("Search books by title")}, + {"id":2, "title":_("Search by authors"), "term":obj, "descr": _("Search authors by name")}, + {"id":3, "title":_("Search series"), "term":obj, "descr": _("Search series")}, + ] + + def item_link(self, item): + if item["id"] == 1: + return reverse("opds_catalog:searchbooks", kwargs={"searchtype":"m", "searchterms":item["term"]}) + elif item["id"] == 2: + return reverse("opds_catalog:searchauthors", kwargs={"searchtype":"m", "searchterms":item["term"]}) + elif item["id"] == 3: + return reverse("opds_catalog:searchseries", kwargs={"searchtype":"m", "searchterms":item["term"]}) + return None + + def item_title(self, item): + return item['title'] + + def item_description(self, item): + return item['descr'] + + def item_guid(self, item): + return "st:%s"%item["id"] + + def item_updateddate(self): + return timezone.now() + + def item_enclosures(self, item): + return (opdsEnclosure(self.item_link(item),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) + + +class SearchBooksFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + description_template = "book_description.html" + + def title(self, obj): + return "%s | %s (%s)"%(settings.TITLE,_("Books found"),_("doubles hide") if settings.DOUBLES_HIDE else _("doubles show")) + + def get_object(self, request, searchtype="m", searchterms=None, searchterms0=None, page=1): + if not isinstance(page, int): + page = int(page) + + # Поиск книг по подсроке + if searchtype == 'm': + books = Book.objects.extra(where=["upper(title) like %s"], params=["%%%s%%"%searchterms.upper()]).order_by('title','-docdate') + # Поиск книг по начальной подстроке + elif searchtype == 'b': + books = Book.objects.extra(where=["upper(title) like %s"], params=["%s%%"%searchterms.upper()]).order_by('title','-docdate') + # Поиск книг по точному совпадению наименования + elif searchtype == 'e': + books = Book.objects.extra(where=["upper(title)=%s"], params=["%s"%searchterms.upper()]).order_by('title','-docdate') + # Поиск книг по автору + elif searchtype == 'a': + try: + author_id = int(searchterms) + except: + author_id = 0 + books = Book.objects.filter(authors=author_id).order_by('title','-docdate') + # Поиск книг по серии + elif searchtype == 's': + try: + ser_id = int(searchterms) + except: + ser_id = 0 + books = Book.objects.filter(series=ser_id).order_by('title','-docdate') + # Поиск книг по автору и серии + elif searchtype == "as": + try: + ser_id = int(searchterms0) + author_id = int(searchterms) + except: + ser_id = 0 + author_id = 0 + books = Book.objects.filter(authors=author_id, series=ser_id if ser_id else None).order_by('title','-docdate') + # Поиск книг по жанру + elif searchtype == 'g': + try: + genre_id = int(searchterms) + except: + genre_id = 0 + books = Book.objects.filter(genres=genre_id).order_by('title','-docdate') + # Поиск книг на книжной полке + elif searchtype == 'u': + if settings.AUTH: + books = Book.objects.filter(bookshelf__user=request.user).order_by('-bookshelf__readtime') + else: + books={} + # Поиск дубликатов для книги + elif searchtype == 'd': + book_id = int(searchterms) + mbook = Book.objects.get(id=book_id) + books = Book.objects.filter(title__iexact=mbook.title, authors__in=mbook.authors.all()).exclude(id=book_id).order_by('title','-docdate') + + # prefetch_related on sqlite on items >999 therow error "too many SQL variables" + #if len(books)>0: + #books = books.prefetch_related('authors','genres','series').order_by('title','authors','-docdate') + + # Фильтруем дубликаты + result = [] + prev_title = '' + prev_authors_set = set() + for row in books: + p = {'doubles':0, 'lang_code': row.lang_code, 'filename': row.filename, 'path': row.path, \ + 'registerdate': row.registerdate, 'id': row.id, 'annotation': row.annotation, \ + 'docdate': row.docdate, 'format': row.format, 'title': row.title, 'filesize': row.filesize} + p['authors'] = row.authors.values() + p['genres'] = row.genres.values() + p['series'] = row.series.values() + if settings.DOUBLES_HIDE and (searchtype != 'd'): + title = p['title'] + authors_set = {a['id'] for a in p['authors']} + if title==prev_title and authors_set==prev_authors_set: + result[-1]['doubles']+=1 + else: + result.append(p) + prev_title = title + prev_authors_set = authors_set + else: + result.append(p) + + return {"books":result, "searchterms":searchterms, "searchterms0":searchterms0, "searchtype":searchtype, "page":page} + + def get_link_kwargs(self, obj): + kwargs={"searchtype":obj["searchtype"], "searchterms":obj["searchterms"]} + if obj.get("searchterms0") is not None: + kwargs["searchterms0"]=obj["searchterms0"] + return kwargs + + def link(self, obj): + return reverse("opds_catalog:searchbooks", kwargs=self.get_link_kwargs(obj)) + + def feed_extra_kwargs(self, obj): + kwargs = self.get_link_kwargs(obj) + if obj["page"] != 1: + kwargs["page"]=obj["page"]-1 + prev_url = reverse("opds_catalog:searchbooks", kwargs=kwargs) + else: + prev_url = None + + if obj["page"]*settings.MAXITEMS0 else None} + +class SelectSeriesFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + + def title(self, obj): + return "%s | %s"%(settings.TITLE,_("Series by authors select")) + + def get_object(self, request, searchtype, searchterms): + try: + author_id=int(searchterms) + except: + author_id = 0 + return author_id + + def link(self, obj): + return reverse("opds_catalog:searchbooks",kwargs={'searchtype':"as",'searchterms':obj}) + + def feed_extra_kwargs(self, obj): + return { + "searchTerm_url":"/opds/search/{searchTerms}/", + "start_url":reverse("opds_catalog:main"), + "description_mime_type":"text", + } + + def items(self, obj): + return [ + {"id":1, "title":_("Books by series"), "author":obj, "descr": _("Books by author and series")}, + {"id":2, "title":_("Books outside series"), "author":obj, "descr": _("Books by author outside series")}, + {"id":3, "title":_("Books by alphabet"), "author":obj, "descr": _("Books by author alphabetical order")}, + ] + + def item_link(self, item): + if item["id"] == 1: + return reverse("opds_catalog:searchseries", kwargs={"searchtype":'a', "searchterms":item["author"]}) + elif item["id"] == 2: + return reverse("opds_catalog:searchbooks", kwargs={"searchtype":"as", "searchterms":item["author"], "searchterms0":0}) + elif item["id"] == 3: + return reverse("opds_catalog:searchbooks", kwargs={"searchtype":'a', "searchterms":item["author"]}) + + def item_title(self, item): + return item['title'] + + def item_description(self, item): + return item['descr'] + + def item_guid(self, item): + return "as:%s"%item["id"] + + def item_updateddate(self): + return timezone.now() + + def item_enclosures(self, item): + return (opdsEnclosure(self.item_link(item),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) + + +class SearchAuthorsFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + + def title(self, obj): + return "%s | %s"%(settings.TITLE,_("Authors found")) + + def get_object(self, request, searchterms, searchtype, page=1): + if not isinstance(page, int): + page = int(page) + + if searchtype == 'm': + #concat(last_name,' ',first_name) + authors = Author.objects.extra(where=["upper(concat(last_name,' ',first_name)) like %s"], params=["%%%s%%"%searchterms.upper()]) + elif searchtype == 'b': + authors = Author.objects.extra(where=["upper(concat(last_name,' ',first_name)) like %s"], params=["%s%%"%searchterms.upper()]) + elif searchtype == 'e': + authors = Author.objects.extra(where=["upper(concat(last_name,' ',first_name))=%s"], params=["%s"%searchterms.upper()]) + return {"authors":authors, "searchterms":searchterms, "searchtype":searchtype, "page":page} + + def link(self, obj): + return reverse("opds_catalog:searchauthors", kwargs={"searchtype":obj["searchtype"], "searchterms":obj["searchterms"]}) + + def feed_extra_kwargs(self, obj): + if obj["page"] != 1: + prev_url = reverse("opds_catalog:searchauthors", kwargs={"searchtype":obj["searchtype"], "searchterms":obj["searchterms"], "page":(obj["page"]-1)}) + else: + prev_url = None + + if obj["page"]*settings.MAXITEMS=settings.SPLITITEMS and not title_full: + return reverse("opds_catalog:chars_books", kwargs={"lang_code":self.lang_code,"chars":item.id}) + else: + return reverse("opds_catalog:searchbooks", \ + kwargs={"searchtype":'b' if not title_full else 'e', "searchterms":item.id}) + + def item_enclosures(self, item): + return (opdsEnclosure(self.item_link(item),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) + + +class AuthorsFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + + def link(self, obj): + return self.request.path + + def title(self, obj): + return "%s | %s"%(settings.TITLE,_("Select authors by substring")) + + def feed_extra_kwargs(self, obj): + return { + "searchTerm_url":"/opds/search/{searchTerms}/", + "start_url":reverse("opds_catalog:main"), + "description_mime_type":"text", + } + + def get_object(self, request, lang_code=0, chars = None): + self.lang_code = int(lang_code) + if chars==None: + chars='' + return (len(chars)+1, chars.upper()) + + def items(self, obj): + length, chars = obj + if self.lang_code: + sql="""select %(length)s as l, upper(substring(concat(last_name,' ',first_name),1,%(length)s)) as id, count(*) as cnt + from opds_catalog_author + where lang_code=%(lang_code)s and upper(concat(last_name,' ',first_name)) like '%(chars)s%%%%' + group by upper(substring(concat(last_name,' ',first_name),1,%(length)s)) + order by id"""%{'length':length, 'lang_code':self.lang_code, 'chars':chars} + else: + sql="""select %(length)s as l, upper(substring(concat(last_name,' ',first_name),1,%(length)s)) as id, count(*) as cnt + from opds_catalog_author + where upper(concat(last_name,' ',first_name)) like '%(chars)s%%%%' + group by upper(substring(concat(last_name,' ',first_name),1,%(length)s)) + order by id"""%{'length':length,'chars':chars} + + dataset = Author.objects.raw(sql) + return dataset + + def item_title(self, item): + return "%s"%item.id + + def item_description(self, item): + return _("Found: %s authors")%item.cnt + + def item_link(self, item): + last_name_full = len(item.id)=settings.SPLITITEMS) and not last_name_full: + return reverse("opds_catalog:chars_authors", kwargs={"lang_code":self.lang_code,"chars":item.id}) + else: + return reverse("opds_catalog:searchauthors", \ + kwargs={"searchtype":'b' if not last_name_full else 'e', "searchterms":item.id}) + + def item_enclosures(self, item): + return (opdsEnclosure(self.item_link(item),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) + + +class SeriesFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + + def link(self, obj): + return self.request.path + + def title(self, obj): + return "%s | %s"%(settings.TITLE,_("Select series by substring")) + + def feed_extra_kwargs(self, obj): + return { + "searchTerm_url":"/opds/search/{searchTerms}/", + "start_url":reverse("opds_catalog:main"), + "description_mime_type":"text", + } + + def get_object(self, request, lang_code=0, chars = None): + self.lang_code = int(lang_code) + if chars==None: + chars='' + return (len(chars)+1, chars.upper()) + + def items(self, obj): + length, chars = obj + if self.lang_code: + sql="""select %(length)s as l, upper(substring(ser,1,%(length)s)) as id, count(*) as cnt + from opds_catalog_series + where lang_code=%(lang_code)s and upper(ser) like '%(chars)s%%%%' + group by upper(substring(ser,1,%(length)s)) + order by id"""%{'length':length, 'lang_code':self.lang_code, 'chars':chars} + else: + sql="""select %(length)s as l, upper(substring(ser,1,%(length)s)) as id, count(*) as cnt + from opds_catalog_series + where upper(ser) like '%(chars)s%%%%' + group by upper(substring(ser,1,%(length)s)) + order by id"""%{'length':length,'chars':chars} + + dataset = Series.objects.raw(sql) + return dataset + + def item_title(self, item): + return "%s"%item.id + + def item_description(self, item): + return _("Found: %s series")%item.cnt + + def item_link(self, item): + series_full = len(item.id)=settings.SPLITITEMS and not series_full: + return reverse("opds_catalog:chars_series", kwargs={"lang_code":self.lang_code,"chars":item.id}) + else: + return reverse("opds_catalog:searchseries", \ + kwargs={"searchtype":'b' if not series_full else 'e', "searchterms":item.id}) + + def item_enclosures(self, item): + return (opdsEnclosure(self.item_link(item),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) + +class GenresFeed(AuthFeed): + feed_type = opdsFeed + subtitle = settings.SUBTITLE + + def link(self, obj): + return self.request.path + + def title(self, obj): + return "%s | %s"%(settings.TITLE,_("Select genres (%s)")%(_("section") if obj==0 else _("subsection"))) + + def feed_extra_kwargs(self, obj): + return { + "searchTerm_url":"/opds/search/{searchTerms}/", + "start_url":reverse("opds_catalog:main"), + "description_mime_type":"text", + } + + def get_object(self, request, section = 0): + if not isinstance(section, int): + self.section_id = int(section) + else: + self.section_id = section + return self.section_id + + def items(self, obj): + section_id = obj + if section_id==0: + dataset = Genre.objects.values('section').annotate(section_id=Min('id'), num_book=Count('book')).filter(num_book__gt=0).order_by('section') + else: + section = Genre.objects.get(id=section_id).section + dataset = Genre.objects.filter(section=section).annotate(num_book=Count('book')).filter(num_book__gt=0).values().order_by('subsection') + return dataset + + def item_title(self, item): + return "%s"%(item['section'] if self.section_id==0 else item['subsection']) + + def item_description(self, item): + return _("Found: %s books")%item['num_book'] + + def item_link(self, item): + if self.section_id==0: + return reverse("opds_catalog:genres", kwargs={"section":item['section_id']}) + else: + return reverse("opds_catalog:searchbooks", kwargs={"searchtype":'g', "searchterms":item["id"]}) + + def item_enclosures(self, item): + return (opdsEnclosure(self.item_link(item),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) diff --git a/opds_catalog/fixtures/genre.json b/opds_catalog/fixtures/genre.json new file mode 100644 index 0000000000000000000000000000000000000000..28465b786b21d41a07b1b1767074a800a9c9d0a1 --- /dev/null +++ b/opds_catalog/fixtures/genre.json @@ -0,0 +1,230 @@ +[ +{ "model": "opds_catalog.genre", "pk":1, "fields":{"genre":"economics_ref","subsection":"Деловая литература","section":"Деловая литература"}}, +{ "model": "opds_catalog.genre", "pk":2, "fields":{"genre":"popular_business","subsection":"Карьера, кадры","section":"Деловая литература"}}, +{ "model": "opds_catalog.genre", "pk":3, "fields":{"genre":"org_behavior","subsection":"Маркетинг, PR","section":"Деловая литература"}}, +{ "model": "opds_catalog.genre", "pk":4, "fields":{"genre":"banking","subsection":"Финансы","section":"Деловая литература"}}, +{ "model": "opds_catalog.genre", "pk":5, "fields":{"genre":"economics","subsection":"Экономика","section":"Деловая литература"}}, +{ "model": "opds_catalog.genre", "pk":6, "fields":{"genre":"det_action","subsection":"Боевик","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":7, "fields":{"genre":"detective","subsection":"Детективы","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":8, "fields":{"genre":"det_irony","subsection":"Иронический детектив, дамский детективный роман","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":9, "fields":{"genre":"det_history","subsection":"Исторический детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":10, "fields":{"genre":"det_classic","subsection":"Классический детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":11, "fields":{"genre":"det_crime","subsection":"Криминальный детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":12, "fields":{"genre":"det_hard","subsection":"Крутой детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":13, "fields":{"genre":"det_political","subsection":"Политический детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":14, "fields":{"genre":"det_police","subsection":"Полицейский детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":15, "fields":{"genre":"det_maniac","subsection":"Про маньяков","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":16, "fields":{"genre":"det_su","subsection":"Советский детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":17, "fields":{"genre":"thriller","subsection":"Триллер","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":18, "fields":{"genre":"det_espionage","subsection":"Шпионский детектив","section":"Детективы и Триллеры"}}, +{ "model": "opds_catalog.genre", "pk":19, "fields":{"genre":"nonf_biography","subsection":"Биографии и Мемуары","section":"Документальная литература"}}, +{ "model": "opds_catalog.genre", "pk":20, "fields":{"genre":"nonf_military","subsection":"Военная документалистика и аналитика","section":"Документальная литература"}}, +{ "model": "opds_catalog.genre", "pk":21, "fields":{"genre":"military_special","subsection":"Военное дело","section":"Документальная литература"}}, +{ "model": "opds_catalog.genre", "pk":22, "fields":{"genre":"travel_notes","subsection":"География, путевые заметки","section":"Документальная литература"}}, +{ "model": "opds_catalog.genre", "pk":23, "fields":{"genre":"nonfiction","subsection":"Документальная литература","section":"Документальная литература"}}, +{ "model": "opds_catalog.genre", "pk":24, "fields":{"genre":"nonf_publicism","subsection":"Публицистика","section":"Документальная литература"}}, +{ "model": "opds_catalog.genre", "pk":25, "fields":{"genre":"auto_regulations","subsection":"Автомобили и ПДД","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":26, "fields":{"genre":"home_sport","subsection":"Боевые искусства, спорт","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":27, "fields":{"genre":"home_pets","subsection":"Домашние животные","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":28, "fields":{"genre":"home","subsection":"Домоводство","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":29, "fields":{"genre":"home_health","subsection":"Здоровье","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":30, "fields":{"genre":"home_collecting","subsection":"Коллекционирование","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":31, "fields":{"genre":"home_cooking","subsection":"Кулинария","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":32, "fields":{"genre":"sci_pedagogy","subsection":"Педагогика, воспитание детей, литература для родителей","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":33, "fields":{"genre":"home_entertain","subsection":"Развлечения","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":34, "fields":{"genre":"home_garden","subsection":"Сад и огород","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":35, "fields":{"genre":"home_diy","subsection":"Сделай сам","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":36, "fields":{"genre":"family","subsection":"Семейные отношения","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":37, "fields":{"genre":"home_sex","subsection":"Семейные отношения, секс","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":38, "fields":{"genre":"home_crafts","subsection":"Хобби и ремесла","section":"Дом и семья"}}, +{ "model": "opds_catalog.genre", "pk":39, "fields":{"genre":"drama_antique","subsection":"Античная драма","section":"Драматургия"}}, +{ "model": "opds_catalog.genre", "pk":40, "fields":{"genre":"drama","subsection":"Драма","section":"Драматургия"}}, +{ "model": "opds_catalog.genre", "pk":41, "fields":{"genre":"dramaturgy","subsection":"Драматургия","section":"Драматургия"}}, +{ "model": "opds_catalog.genre", "pk":42, "fields":{"genre":"comedy","subsection":"Комедия","section":"Драматургия"}}, +{ "model": "opds_catalog.genre", "pk":43, "fields":{"genre":"vaudeville","subsection":"Мистерия, буффонада, водевиль","section":"Драматургия"}}, +{ "model": "opds_catalog.genre", "pk":44, "fields":{"genre":"screenplays","subsection":"Сценарий","section":"Драматургия"}}, +{ "model": "opds_catalog.genre", "pk":45, "fields":{"genre":"tragedy","subsection":"Трагедия","section":"Драматургия"}}, +{ "model": "opds_catalog.genre", "pk":46, "fields":{"genre":"painting","subsection":"Живопись, альбомы, иллюстрированные каталоги","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":47, "fields":{"genre":"design","subsection":"Искусство и Дизайн","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":48, "fields":{"genre":"art_criticism","subsection":"Искусствоведение","section":"Искусттво, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":49, "fields":{"genre":"cine","subsection":"Кино","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":50, "fields":{"genre":"nonf_criticism","subsection":"Критика","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":51, "fields":{"genre":"sci_culture","subsection":"Культурология","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":52, "fields":{"genre":"art_world_culture","subsection":"Мировая художественная культура","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":53, "fields":{"genre":"music","subsection":"Музыка","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":54, "fields":{"genre":"notes","subsection":"Партитуры","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":55, "fields":{"genre":"architecture_book","subsection":"Скульптура и архитектура","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":56, "fields":{"genre":"theatre","subsection":"Театр","section":"Искусство, Искусствоведение, Дизайн"}}, +{ "model": "opds_catalog.genre", "pk":57, "fields":{"genre":"computers","subsection":"Зарубежная компьютерная, околокомпьютерная литература","section":"Компьютеры и Интернет"}}, +{ "model": "opds_catalog.genre", "pk":58, "fields":{"genre":"comp_hard","subsection":"Компьютерное 'железо'","section":"Компьютеры и Интернет"}}, +{ "model": "opds_catalog.genre", "pk":59, "fields":{"genre":"comp_www","subsection":"ОС и Сети, интернет","section":"Компьютеры и Интернет"}}, +{ "model": "opds_catalog.genre", "pk":60, "fields":{"genre":"comp_db","subsection":"Программирование, программы, базы данных","section":"Компьютеры и Интернет"}}, +{ "model": "opds_catalog.genre", "pk":61, "fields":{"genre":"tbg_computers","subsection":"Учебные пособия, самоучители","section":"Компьютеры и Интернет"}}, +{ "model": "opds_catalog.genre", "pk":62, "fields":{"genre":"children","subsection":"Детская литература","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":63, "fields":{"genre":"child_education","subsection":"Детская образовательная литература","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":64, "fields":{"genre":"child_det","subsection":"Детская остросюжетная литература","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":65, "fields":{"genre":"foreign_children","subsection":"Зарубежная литература для детей","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":66, "fields":{"genre":"prose_game","subsection":"Игры, упражнения для детей","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":67, "fields":{"genre":"child_classical","subsection":"Классическая детская литература","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":68, "fields":{"genre":"child_prose","subsection":"Проза для детей","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":69, "fields":{"genre":"child_tale_rus","subsection":"Русские сказки","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":70, "fields":{"genre":"child_tale","subsection":"Сказки народов мира","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":71, "fields":{"genre":"child_verse","subsection":"Стихи для детей","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":72, "fields":{"genre":"child_sf","subsection":"Фантастика для детей","section":"Литература для детей"}}, +{ "model": "opds_catalog.genre", "pk":73, "fields":{"genre":"love_history","subsection":"Исторические любовные романы","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":74, "fields":{"genre":"love_short","subsection":"Короткие любовные романы","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":75, "fields":{"genre":"love_sf","subsection":"Любовное фэнтези, любовно-фантастические романы","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":76, "fields":{"genre":"love","subsection":"Любовные романы","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":77, "fields":{"genre":"love_detective","subsection":"Остросюжетные любовные романы","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":78, "fields":{"genre":"love_hard","subsection":"Порно","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":79, "fields":{"genre":"love_contemporary","subsection":"Современные любовные романы","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":80, "fields":{"genre":"love_erotica","subsection":"Эротическая литература","section":"Любовные романы"}}, +{ "model": "opds_catalog.genre", "pk":81, "fields":{"genre":"sci_medicine_alternative","subsection":"Альтернативная медицина","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":82, "fields":{"genre":"sci_theories","subsection":"Альтернативные науки и научные теории","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":83, "fields":{"genre":"sci_cosmos","subsection":"Астрономия и Космос","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":84, "fields":{"genre":"sci_biology","subsection":"Биология, биофизика, биохимия","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":85, "fields":{"genre":"sci_botany","subsection":"Ботаника","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":86, "fields":{"genre":"sci_veterinary","subsection":"Ветеринария","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":87, "fields":{"genre":"military_history","subsection":"Военная история","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":88, "fields":{"genre":"sci_oriental","subsection":"Востоковедение","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":89, "fields":{"genre":"sci_geo","subsection":"Геология и география","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":90, "fields":{"genre":"sci_state","subsection":"Государство и право","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":91, "fields":{"genre":"sci_popular","subsection":"Зарубежная образовательная литература, зарубежная прикладная, научно-популярная литература","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":92, "fields":{"genre":"sci_zoo","subsection":"Зоология","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":93, "fields":{"genre":"sci_history","subsection":"История","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":94, "fields":{"genre":"sci_philology","subsection":"Литературоведение","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":95, "fields":{"genre":"sci_math","subsection":"Математика","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":96, "fields":{"genre":"sci_medicine","subsection":"Медицина","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":97, "fields":{"genre":"science","subsection":"Научная литература","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":98, "fields":{"genre":"sci_social_studies","subsection":"Обществознание, социология","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":99, "fields":{"genre":"sci_politics","subsection":"Политика","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":100, "fields":{"genre":"sci_psychology","subsection":"Психология и психотерапия","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":101, "fields":{"genre":"sci_phys","subsection":"Физика","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":102, "fields":{"genre":"sci_philosophy","subsection":"Философия","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":103, "fields":{"genre":"sci_chem","subsection":"Химия","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":104, "fields":{"genre":"sci_ecology","subsection":"Экология","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":105, "fields":{"genre":"sci_economy","subsection":"Экономика","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":106, "fields":{"genre":"sci_juris","subsection":"Юриспруденция","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":107, "fields":{"genre":"sci_linguistic","subsection":"Языкознание, иностранные языки","section":"Наука, Образование"}}, +{ "model": "opds_catalog.genre", "pk":108, "fields":{"genre":"palindromes","subsection":"Визуальная и экспериментальная поэзия, верлибры, палиндромы","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":109, "fields":{"genre":"poetry_for_classical","subsection":"Классическая зарубежная поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":110, "fields":{"genre":"poetry_classical","subsection":"Классическая поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":111, "fields":{"genre":"poetry_rus_classical","subsection":"Классическая русская поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":112, "fields":{"genre":"lyrics","subsection":"Лирика","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":113, "fields":{"genre":"song_poetry","subsection":"Песенная поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":114, "fields":{"genre":"poetry","subsection":"Поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":115, "fields":{"genre":"poetry_east","subsection":"Поэзия Востока","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":116, "fields":{"genre":"poem","subsection":"Поэма, эпическая поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":117, "fields":{"genre":"poetry_for_modern","subsection":"Современная зарубежная поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":118, "fields":{"genre":"poetry_modern","subsection":"Современная поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":119, "fields":{"genre":"poetry_rus_modern","subsection":"Современная русская поэзия","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":120, "fields":{"genre":"humor_verse","subsection":"Юмористические стихи, басни","section":"Поэзия"}}, +{ "model": "opds_catalog.genre", "pk":121, "fields":{"genre":"adv_story","subsection":"Авантюрный роман","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":122, "fields":{"genre":"adv_indian","subsection":"Вестерн, про индейцев","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":123, "fields":{"genre":"adv_history","subsection":"Исторические приключения","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":124, "fields":{"genre":"adv_maritime","subsection":"Морские приключения","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":125, "fields":{"genre":"adventure","subsection":"Приключения","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":126, "fields":{"genre":"adv_modern","subsection":"Приключения в современном мире","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":127, "fields":{"genre":"child_adv","subsection":"Приключения для детей и подростков","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":128, "fields":{"genre":"adv_animal","subsection":"Природа и животные","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":129, "fields":{"genre":"adv_geo","subsection":"Путешествия и география","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":130, "fields":{"genre":"tale_chivalry","subsection":"Рыцарский роман","section":"Приключения"}}, +{ "model": "opds_catalog.genre", "pk":131, "fields":{"genre":"aphorisms","subsection":"Афоризмы, цитаты","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":132, "fields":{"genre":"gothic_novel","subsection":"Готический роман","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":133, "fields":{"genre":"foreign_prose","subsection":"Зарубежная классическая проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":134, "fields":{"genre":"prose_history","subsection":"Историческая проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":135, "fields":{"genre":"prose_classic","subsection":"Классическая проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":136, "fields":{"genre":"literature_18","subsection":"Классическая проза XVII-XVIII веков","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":137, "fields":{"genre":"literature_19","subsection":"Классическая проза ХIX века","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":138, "fields":{"genre":"literature_20","subsection":"Классическая проза ХX века","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":139, "fields":{"genre":"prose_counter","subsection":"Контркультура","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":140, "fields":{"genre":"prose_magic","subsection":"Магический реализм","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":141, "fields":{"genre":"story","subsection":"Малые литературные формы прозы: рассказы, эссе, новеллы, феерия","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":142, "fields":{"genre":"prose","subsection":"Проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":143, "fields":{"genre":"prose_military","subsection":"Проза о войне","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":144, "fields":{"genre":"great_story","subsection":"Роман, повесть","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":145, "fields":{"genre":"prose_rus_classic","subsection":"Русская классическая проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":146, "fields":{"genre":"prose_su_classics","subsection":"Советская классическая проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":147, "fields":{"genre":"prose_contemporary","subsection":"Современная русская и зарубежная проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":148, "fields":{"genre":"foreign_antique","subsection":"Средневековая классическая проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":149, "fields":{"genre":"prose_abs","subsection":"Фантасмагория, абсурдистская проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":150, "fields":{"genre":"prose_neformatny","subsection":"Экспериментальная, неформатная проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":151, "fields":{"genre":"epistolary_fiction","subsection":"Эпистолярная проза","section":"Проза"}}, +{ "model": "opds_catalog.genre", "pk":152, "fields":{"genre":"periodic","subsection":"Журналы, газеты","section":"Прочее"}}, +{ "model": "opds_catalog.genre", "pk":153, "fields":{"genre":"comics","subsection":"Комиксы","section":"Прочее"}}, +{ "model": "opds_catalog.genre", "pk":154, "fields":{"genre":"unfinished","subsection":"Незавершенное","section":"Прочее"}}, +{ "model": "opds_catalog.genre", "pk":155, "fields":{"genre":"other","subsection":"Неотсортированное","section":"Прочее"}}, +{ "model": "opds_catalog.genre", "pk":156, "fields":{"genre":"network_literature","subsection":"Самиздат, сетевая литература","section":"Прочее"}}, +{ "model": "opds_catalog.genre", "pk":157, "fields":{"genre":"fanfiction","subsection":"Фанфик","section":"Прочее"}}, +{ "model": "opds_catalog.genre", "pk":158, "fields":{"genre":"astrology","subsection":"Астрология и хиромантия","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":159, "fields":{"genre":"religion_budda","subsection":"Буддизм","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":160, "fields":{"genre":"religion_hinduism","subsection":"Индуизм","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":161, "fields":{"genre":"religion_islam","subsection":"Ислам","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":162, "fields":{"genre":"religion_judaism","subsection":"Иудаизм","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":163, "fields":{"genre":"religion_catholicism","subsection":"Католицизм","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":164, "fields":{"genre":"religion_orthodoxy","subsection":"Православие","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":165, "fields":{"genre":"religion_protestantism","subsection":"Протестантизм","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":166, "fields":{"genre":"sci_religion","subsection":"Религиоведение","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":167, "fields":{"genre":"religion","subsection":"Религия, религиозная литература","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":168, "fields":{"genre":"religion_self","subsection":"Самосовершенствование","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":169, "fields":{"genre":"religion_christianity","subsection":"Христианство","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":170, "fields":{"genre":"religion_esoterics","subsection":"Эзотерика, эзотерическая литература","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":171, "fields":{"genre":"religion_paganism","subsection":"Язычество","section":"Религия, духовность, эзотерика"}}, +{ "model": "opds_catalog.genre", "pk":172, "fields":{"genre":"geo_guides","subsection":"Путеводители, карты, атласы","section":"Справочная литература"}}, +{ "model": "opds_catalog.genre", "pk":173, "fields":{"genre":"ref_guide","subsection":"Руководства","section":"Справочная литература"}}, +{ "model": "opds_catalog.genre", "pk":174, "fields":{"genre":"ref_dict","subsection":"Словари","section":"Справочная литература"}}, +{ "model": "opds_catalog.genre", "pk":175, "fields":{"genre":"reference","subsection":"Справочная литература","section":"Справочная литература"}}, +{ "model": "opds_catalog.genre", "pk":176, "fields":{"genre":"ref_ref","subsection":"Справочники","section":"Справочная литература"}}, +{ "model": "opds_catalog.genre", "pk":177, "fields":{"genre":"ref_encyc","subsection":"Энциклопедии","section":"Справочная литература"}}, +{ "model": "opds_catalog.genre", "pk":178, "fields":{"genre":"antique","subsection":"antique","section":"Старинное"}}, +{ "model": "opds_catalog.genre", "pk":179, "fields":{"genre":"antique_ant","subsection":"Античная литература","section":"Старинное"}}, +{ "model": "opds_catalog.genre", "pk":180, "fields":{"genre":"antique_east","subsection":"Древневосточная литература","section":"Старинное"}}, +{ "model": "opds_catalog.genre", "pk":181, "fields":{"genre":"antique_russian","subsection":"Древнерусская литература","section":"Старинное"}}, +{ "model": "opds_catalog.genre", "pk":182, "fields":{"genre":"antique_european","subsection":"Европейская старинная литература","section":"Старинное"}}, +{ "model": "opds_catalog.genre", "pk":183, "fields":{"genre":"auto_business","subsection":"Автодело","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":184, "fields":{"genre":"military_weapon","subsection":"Военное дело, военная техника и вооружение","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":185, "fields":{"genre":"equ_history","subsection":"История техники","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":186, "fields":{"genre":"sci_metal","subsection":"Металлургия","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":187, "fields":{"genre":"sci_radio","subsection":"Радиоэлектроника","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":188, "fields":{"genre":"sci_build","subsection":"Строительство и сопромат","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":189, "fields":{"genre":"sci_tech","subsection":"Технические науки","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":190, "fields":{"genre":"sci_transport","subsection":"Транспорт и авиация","section":"Техника"}}, +{ "model": "opds_catalog.genre", "pk":191, "fields":{"genre":"sci_textbook","subsection":"Учебники и пособия","section":"Учебники и пособия"}}, +{ "model": "opds_catalog.genre", "pk":192, "fields":{"genre":"tbg_higher","subsection":"Учебники и пособия ВУЗов","section":"Учебники и пособия"}}, +{ "model": "opds_catalog.genre", "pk":193, "fields":{"genre":"tbg_secondary","subsection":"Учебники и пособия для среднего и специального образования","section":"Учебники и пособия"}}, +{ "model": "opds_catalog.genre", "pk":194, "fields":{"genre":"tbg_school","subsection":"Школьные учебники и пособия, рефераты, шпаргалки","section":"Учебники и пособия"}}, +{ "model": "opds_catalog.genre", "pk":195, "fields":{"genre":"sf_history","subsection":"Альтернативная история, попаданцы","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":196, "fields":{"genre":"sf_action","subsection":"Боевая фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":197, "fields":{"genre":"sf_heroic","subsection":"Героическая фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":198, "fields":{"genre":"sf_fantasy_city","subsection":"Городское фэнтези","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":199, "fields":{"genre":"sf_detective","subsection":"Детективная фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":200, "fields":{"genre":"sf_cyberpunk","subsection":"Киберпанк","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":201, "fields":{"genre":"sf_space","subsection":"Космическая фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":202, "fields":{"genre":"sf_mystic","subsection":"Мистика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":203, "fields":{"genre":"fairy_fantasy","subsection":"Мифологическое фэнтези","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":204, "fields":{"genre":"sf","subsection":"Научная Фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":205, "fields":{"genre":"sf_postapocalyptic","subsection":"Постапокалипсис","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":206, "fields":{"genre":"russian_fantasy","subsection":"Славянское фэнтези","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":207, "fields":{"genre":"modern_tale","subsection":"Современная сказка","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":208, "fields":{"genre":"sf_social","subsection":"Социально-психологическая фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":209, "fields":{"genre":"sf_stimpank","subsection":"Стимпанк","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":210, "fields":{"genre":"sf_technofantasy","subsection":"Технофэнтези","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":211, "fields":{"genre":"sf_horror","subsection":"Ужасы","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":212, "fields":{"genre":"sf_etc","subsection":"Фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":213, "fields":{"genre":"sf_fantasy","subsection":"Фэнтези","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":214, "fields":{"genre":"hronoopera","subsection":"Хроноопера","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":215, "fields":{"genre":"sf_epic","subsection":"Эпическая фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":216, "fields":{"genre":"sf_humor","subsection":"Юмористическая фантастика","section":"Фантастика"}}, +{ "model": "opds_catalog.genre", "pk":217, "fields":{"genre":"epic","subsection":"Былины, эпопея","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":218, "fields":{"genre":"child_folklore","subsection":"Детский фольклор","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":219, "fields":{"genre":"antique_myths","subsection":"Мифы. Легенды. Эпос","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":220, "fields":{"genre":"folk_songs","subsection":"Народные песни","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":221, "fields":{"genre":"folk_tale","subsection":"Народные сказки","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":222, "fields":{"genre":"proverbs","subsection":"Пословицы, поговорки","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":223, "fields":{"genre":"folklore","subsection":"Фольклор, загадки folklore","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":224, "fields":{"genre":"limerick","subsection":"Частушки, прибаутки, потешки","section":"Фольклор"}}, +{ "model": "opds_catalog.genre", "pk":225, "fields":{"genre":"humor_anecdote","subsection":"Анекдоты","section":"Юмор"}}, +{ "model": "opds_catalog.genre", "pk":226, "fields":{"genre":"humor_satire","subsection":"Сатира","section":"Юмор"}}, +{ "model": "opds_catalog.genre", "pk":227, "fields":{"genre":"humor","subsection":"Юмор","section":"Юмор"}}, +{ "model": "opds_catalog.genre", "pk":228, "fields":{"genre":"humor_prose","subsection":"Юмористическая проза","section":"Юмор"}} +] diff --git a/opds_catalog/fixtures/testdb.json b/opds_catalog/fixtures/testdb.json new file mode 100644 index 0000000000000000000000000000000000000000..2fb009c319034bff3310bd81b6f234ca5d0eb076 --- /dev/null +++ b/opds_catalog/fixtures/testdb.json @@ -0,0 +1 @@ +[{"model": "opds_catalog.book", "pk": 1466, "fields": {"filename": "262001.fb2", "path": ".", "filesize": 503533, "format": "fb2", "catalog": 11, "cat_type": 0, "registerdate": "2016-07-08T18:24:14.003Z", "docdate": "30.1.2011", "lang": "en", "title": "The Sanctuary Sparrow", "annotation": "", "avail": 2}}, {"model": "opds_catalog.book", "pk": 1467, "fields": {"filename": "539603.fb2", "path": "books.zip", "filesize": 15194, "format": "fb2", "catalog": 12, "cat_type": 1, "registerdate": "2016-07-08T18:24:14.019Z", "docdate": "130552595662030000", "lang": "ru", "title": "\u041b\u044e\u0431\u043e\u0432\u044c \u0432 \u0436\u0438\u0437\u043d\u0438 \u041e\u0431\u043b\u043e\u043c\u043e\u0432\u0430", "annotation": "\u041b\u0435\u0442 \u0442\u043e\u043c\u0443 \u0432\u043e\u0441\u0435\u043c\u044c \u043d\u0430\u0437\u0430\u0434 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u0435\u043b\u044c \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0441\u0438\u0431\u0438\u0440\u0441\u043a\u043e\u0433\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0430 \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0441\u044f \u043a\u043e \u043c\u043d\u0435 \u0441 \u043f\u0440\u043e\u0441\u044c\u0431\u043e\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u0447\u0438\u043d\u0435\u043d\u0438\u0435, \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u0442\u0435\u0445, \u0447\u0442\u043e \u043f\u0438\u0448\u0443\u0442 \u0448\u043a\u043e\u043b\u044c\u043d\u0438\u043a\u0438. \u041c\u043d\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u043b\u0438 \u0432\u0437\u044f\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438\u0437 \u0448\u043a\u043e\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u00ab\u043e\u0431\u0440\u0430\u0437\u00bb \u043b\u044e\u0431\u043e\u0433\u043e \u0438\u0437 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439. \u041f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c, \u0438 \u044f \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u043b\u0441\u044f. \u041d\u0430\u043f\u0438\u0441\u0430\u043b \u0441\u043e\u0447\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u043e \u0440\u043e\u043c\u0430\u043d\u0443 \u0418\u0432\u0430\u043d\u0430 \u0413\u043e\u043d\u0447\u0430\u0440\u043e\u0432\u0430 \u00ab\u041e\u0431\u043b\u043e\u043c\u043e\u0432\u00bb \u0438 \u0434\u0430\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0437\u0430 \u043d\u0435\u0433\u043e \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0434\u0435\u043d\u0435\u0436\u043a\u0443. \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0441\u0431\u043e\u0440\u043d\u0438\u043a\u0430 \u043c\u043d\u0435 \u0442\u0430\u043a \u0438 \u043d\u0435 \u043f\u0440\u0438\u0441\u043b\u0430\u043b\u0438.\n\u0418 \u0432\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0451\u043b \u044f \u0441\u0440\u0435\u0434\u0438 \u0437\u0430\u043c\u0448\u0435\u043b\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u044d\u0442\u043e\u0442 \u0442\u0435\u043a\u0441\u0442 \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u0430\u0448\u0435\u043c\u0443 \u0431\u043b\u0430\u0433\u043e\u0441\u043a\u043b\u043e\u043d\u043d\u043e\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e. \u041c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0442\u0435\u043a\u0441\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u0435\u043d.", "avail": 2}}, {"model": "opds_catalog.book", "pk": 1468, "fields": {"filename": "539485.fb2", "path": "books.zip", "filesize": 12293, "format": "fb2", "catalog": 12, "cat_type": 1, "registerdate": "2016-07-08T18:24:14.024Z", "docdate": "2010-07-23 09:35:56", "lang": "bg", "title": "\u041a\u0438\u0442\u0430\u0439\u0441\u043a\u0438 \u0441\u043b\u0430\u0434\u043a\u0438\u0448 \u0441 \u043a\u044a\u0441\u043c\u0435\u0442\u0447\u0435", "annotation": "", "avail": 2}}, {"model": "opds_catalog.book", "pk": 1469, "fields": {"filename": "539273.fb2", "path": "books.zip", "filesize": 21722, "format": "fb2", "catalog": 12, "cat_type": 1, "registerdate": "2016-07-08T18:24:14.033Z", "docdate": "2014-06-11 08:25:05", "lang": "ru", "title": "\u0414\u0440\u0430\u043a\u043e\u043d\u044c\u0438 \u0423\u0441\u043b\u0443\u0433\u0438", "annotation": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u0430\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0434\u0440\u0430\u043a\u043e\u043d\u043e\u0432 \u0438 \u043f\u0440\u0438\u043d\u0446\u0435\u0441\u0441. \u0412\u0435\u0434\u044c \u044d\u0442\u043e \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0442\u0435\u043c\u0430, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0451 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u043e, \u0447\u0442\u043e \u0434\u0440\u0430\u043a\u043e\u043d\u044b \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0431\u044b \u043f\u0440\u0438\u043d\u0446\u0435\u0441\u0441\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u043b\u0438 \u0441\u0432\u043e\u044e \u0441\u0430\u043c\u043e\u043e\u0446\u0435\u043d\u043a\u0443.", "avail": 2}}, {"model": "opds_catalog.catalog", "pk": 11, "fields": {"parent": null, "cat_name": ".", "path": ".", "cat_type": 0}}, {"model": "opds_catalog.catalog", "pk": 12, "fields": {"parent": 11, "cat_name": "books.zip", "path": "books.zip", "cat_type": 1}}, {"model": "opds_catalog.author", "pk": 1031, "fields": {"first_name": "Ellis", "last_name": "Peters"}}, {"model": "opds_catalog.author", "pk": 1032, "fields": {"first_name": "\u0421\u0432\u044f\u0442\u043e\u0441\u043b\u0430\u0432", "last_name": "\u041b\u043e\u0433\u0438\u043d\u043e\u0432"}}, {"model": "opds_catalog.author", "pk": 1033, "fields": {"first_name": "\u0427\u0430\u0440\u043b\u0437", "last_name": "\u0424\u0440\u0438\u0447"}}, {"model": "opds_catalog.author", "pk": 1034, "fields": {"first_name": "\u0414\u0435\u043d\u0438\u0441", "last_name": "\u041a\u0443\u043f\u0440\u0438\u044f\u043d\u043e\u0432"}}, {"model": "opds_catalog.bauthor", "pk": 1931, "fields": {"book": 1466, "author": 1031}}, {"model": "opds_catalog.bauthor", "pk": 1932, "fields": {"book": 1467, "author": 1032}}, {"model": "opds_catalog.bauthor", "pk": 1933, "fields": {"book": 1468, "author": 1033}}, {"model": "opds_catalog.bauthor", "pk": 1934, "fields": {"book": 1469, "author": 1034}}, {"model": "opds_catalog.genre", "pk": 266, "fields": {"genre": "antique", "section": "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0436\u0430\u043d\u0440", "subsection": "antique"}}, {"model": "opds_catalog.genre", "pk": 267, "fields": {"genre": "nonf_criticism", "section": "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0436\u0430\u043d\u0440", "subsection": "nonf_criticism"}}, {"model": "opds_catalog.genre", "pk": 268, "fields": {"genre": "prose_classic", "section": "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0436\u0430\u043d\u0440", "subsection": "prose_classic"}}, {"model": "opds_catalog.genre", "pk": 269, "fields": {"genre": "prose_contemporary", "section": "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0436\u0430\u043d\u0440", "subsection": "prose_contemporary"}}, {"model": "opds_catalog.bgenre", "pk": 1496, "fields": {"book": 1466, "genre": 266}}, {"model": "opds_catalog.bgenre", "pk": 1497, "fields": {"book": 1467, "genre": 267}}, {"model": "opds_catalog.bgenre", "pk": 1498, "fields": {"book": 1468, "genre": 268}}, {"model": "opds_catalog.bgenre", "pk": 1499, "fields": {"book": 1469, "genre": 269}}, {"model": "opds_catalog.counter", "pk": "allauthors", "fields": {"value": 4, "update_time": "2016-07-08T18:24:14.470Z"}}, {"model": "opds_catalog.counter", "pk": "allbooks", "fields": {"value": 4, "update_time": "2016-07-08T18:24:14.247Z"}}, {"model": "opds_catalog.counter", "pk": "allcatalogs", "fields": {"value": 2, "update_time": "2016-07-08T18:24:14.361Z"}}, {"model": "opds_catalog.counter", "pk": "allgenres", "fields": {"value": 4, "update_time": "2016-07-08T18:24:14.581Z"}}, {"model": "opds_catalog.counter", "pk": "allseries", "fields": {"value": 0, "update_time": "2016-07-08T18:24:14.682Z"}}, {"model": "auth.permission", "pk": 1, "fields": {"name": "Can add log entry", "content_type": 1, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change log entry", "content_type": 1, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete log entry", "content_type": 1, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can add permission", "content_type": 2, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can change permission", "content_type": 2, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can delete permission", "content_type": 2, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can add group", "content_type": 3, "codename": "add_group"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can change group", "content_type": 3, "codename": "change_group"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can delete group", "content_type": 3, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can add user", "content_type": 4, "codename": "add_user"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can change user", "content_type": 4, "codename": "change_user"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can delete user", "content_type": 4, "codename": "delete_user"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add content type", "content_type": 5, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change content type", "content_type": 5, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete content type", "content_type": 5, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can add session", "content_type": 6, "codename": "add_session"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can change session", "content_type": 6, "codename": "change_session"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can delete session", "content_type": 6, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can add book", "content_type": 7, "codename": "add_book"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can change book", "content_type": 7, "codename": "change_book"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can delete book", "content_type": 7, "codename": "delete_book"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can add catalog", "content_type": 8, "codename": "add_catalog"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can change catalog", "content_type": 8, "codename": "change_catalog"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can delete catalog", "content_type": 8, "codename": "delete_catalog"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add author", "content_type": 9, "codename": "add_author"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change author", "content_type": 9, "codename": "change_author"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete author", "content_type": 9, "codename": "delete_author"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can add bauthor", "content_type": 10, "codename": "add_bauthor"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can change bauthor", "content_type": 10, "codename": "change_bauthor"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can delete bauthor", "content_type": 10, "codename": "delete_bauthor"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can add genre", "content_type": 11, "codename": "add_genre"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can change genre", "content_type": 11, "codename": "change_genre"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can delete genre", "content_type": 11, "codename": "delete_genre"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can add bgenre", "content_type": 12, "codename": "add_bgenre"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can change bgenre", "content_type": 12, "codename": "change_bgenre"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can delete bgenre", "content_type": 12, "codename": "delete_bgenre"}}, {"model": "auth.permission", "pk": 37, "fields": {"name": "Can add series", "content_type": 13, "codename": "add_series"}}, {"model": "auth.permission", "pk": 38, "fields": {"name": "Can change series", "content_type": 13, "codename": "change_series"}}, {"model": "auth.permission", "pk": 39, "fields": {"name": "Can delete series", "content_type": 13, "codename": "delete_series"}}, {"model": "auth.permission", "pk": 40, "fields": {"name": "Can add bseries", "content_type": 14, "codename": "add_bseries"}}, {"model": "auth.permission", "pk": 41, "fields": {"name": "Can change bseries", "content_type": 14, "codename": "change_bseries"}}, {"model": "auth.permission", "pk": 42, "fields": {"name": "Can delete bseries", "content_type": 14, "codename": "delete_bseries"}}, {"model": "auth.permission", "pk": 43, "fields": {"name": "Can add bookshelf", "content_type": 15, "codename": "add_bookshelf"}}, {"model": "auth.permission", "pk": 44, "fields": {"name": "Can change bookshelf", "content_type": 15, "codename": "change_bookshelf"}}, {"model": "auth.permission", "pk": 45, "fields": {"name": "Can delete bookshelf", "content_type": 15, "codename": "delete_bookshelf"}}, {"model": "auth.permission", "pk": 46, "fields": {"name": "Can add counter", "content_type": 16, "codename": "add_counter"}}, {"model": "auth.permission", "pk": 47, "fields": {"name": "Can change counter", "content_type": 16, "codename": "change_counter"}}, {"model": "auth.permission", "pk": 48, "fields": {"name": "Can delete counter", "content_type": 16, "codename": "delete_counter"}}] \ No newline at end of file diff --git a/opds_catalog/locale/ru/LC_MESSAGES/django.mo b/opds_catalog/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..25cb0de0936a2ef7afa192548c1af2ba65ae01b9 Binary files /dev/null and b/opds_catalog/locale/ru/LC_MESSAGES/django.mo differ diff --git a/opds_catalog/locale/ru/LC_MESSAGES/django.po b/opds_catalog/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..baa221a98dc845cd5e607528bd5ba9198ad4bb31 --- /dev/null +++ b/opds_catalog/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,271 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-11-07 00:41+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: \n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%" +"100>=11 && n%100<=14)? 2 : 3);\n" + +#: .\opds_catalog\feeds.py:119 .\opds_catalog\tests\test_feeds.py:76 +#, python-format +msgid "All books by %(last_name)s %(first_name)s" +msgstr "Все книги автора %(last_name)s %(first_name)s" + +#: .\opds_catalog\feeds.py:131 +msgid "Book doublicates" +msgstr "Дубликаты книги" + +#: .\opds_catalog\feeds.py:153 .\opds_catalog\feeds.py:211 +#: .\opds_catalog\feeds.py:213 .\opds_catalog\tests\test_feeds.py:22 +msgid "By catalogs" +msgstr "По каталогам" + +#: .\opds_catalog\feeds.py:154 .\opds_catalog\tests\test_feeds.py:23 +#, python-format +msgid "Catalogs: %(catalogs)s, books: %(books)s." +msgstr "Каталогов: %(catalogs)s, книг: %(books)s." + +#: .\opds_catalog\feeds.py:155 +msgid "By authors" +msgstr "По авторам" + +#: .\opds_catalog\feeds.py:156 .\opds_catalog\tests\test_feeds.py:24 +#, python-format +msgid "Authors: %(authors)s." +msgstr "Авторов: %(authors)s." + +#: .\opds_catalog\feeds.py:157 +msgid "By titles" +msgstr "По наименованиям" + +#: .\opds_catalog\feeds.py:158 +#, python-format +msgid "Books: %(books)s." +msgstr "Книг: %(books)s." + +#: .\opds_catalog\feeds.py:159 +msgid "By genres" +msgstr "По жанрам" + +#: .\opds_catalog\feeds.py:160 .\opds_catalog\tests\test_feeds.py:25 +#, python-format +msgid "Genres: %(genres)s." +msgstr "Жанров: %(genres)s." + +#: .\opds_catalog\feeds.py:161 +msgid "By series" +msgstr "По сериям" + +#: .\opds_catalog\feeds.py:162 +#, python-format +msgid "Series: %(series)s." +msgstr "Серий: %(series)s." + +#: .\opds_catalog\feeds.py:166 +#, python-format +msgid "%(username)s Book shelf" +msgstr "Книжная полка (%(username)s)" + +#: .\opds_catalog\feeds.py:167 +#, python-format +msgid "%(username)s books readed: %(bookshelf)s." +msgstr "Книг прочитано (%(username)s): %(bookshelf)s." + +#: .\opds_catalog\feeds.py:308 .\opds_catalog\tests\test_feeds.py:58 +msgid "Search by titles" +msgstr "Поиск по наименованиям" + +#: .\opds_catalog\feeds.py:308 +msgid "Search books by title" +msgstr "Поиск книг по наименованию" + +#: .\opds_catalog\feeds.py:309 +msgid "Search by authors" +msgstr "Поиск авторов" + +#: .\opds_catalog\feeds.py:309 +msgid "Search authors by name" +msgstr "Поиск авторов по имени" + +#: .\opds_catalog\feeds.py:310 +msgid "Search series" +msgstr "Поиск серий" + +#: .\opds_catalog\feeds.py:344 +msgid "Books found" +msgstr "Найдены книги" + +#: .\opds_catalog\feeds.py:344 +msgid "doubles hide" +msgstr "дубликаты скрыты" + +#: .\opds_catalog\feeds.py:344 +msgid "doubles show" +msgstr "дубликаты показаны" + +#: .\opds_catalog\feeds.py:504 +msgid "Series by authors select" +msgstr "Выбор серий у автора" + +#: .\opds_catalog\feeds.py:525 +msgid "Books by series" +msgstr "Книги по сериям" + +#: .\opds_catalog\feeds.py:525 +msgid "Books by author and series" +msgstr "Книги по авторам и сериям" + +#: .\opds_catalog\feeds.py:526 +msgid "Books outside series" +msgstr "Книги вне серий" + +#: .\opds_catalog\feeds.py:526 +msgid "Books by author outside series" +msgstr "Книги автора вне серий" + +#: .\opds_catalog\feeds.py:527 +msgid "Books by alphabet" +msgstr "Книги по алфавиту" + +#: .\opds_catalog\feeds.py:527 +msgid "Books by author alphabetical order" +msgstr "Книги автора в алфавитном порядке" + +#: .\opds_catalog\feeds.py:559 +msgid "Authors found" +msgstr "Найдены авторы" + +#: .\opds_catalog\feeds.py:610 .\opds_catalog\feeds.py:686 +#, python-format +msgid "Books count: %s" +msgstr "Всего: %s книг" + +#: .\opds_catalog\feeds.py:626 +msgid "Series found" +msgstr "Найдены серии" + +#: .\opds_catalog\feeds.py:710 +msgid "Select language" +msgstr "Выбор алфавита" + +#: .\opds_catalog\feeds.py:722 .\opds_catalog\models.py:16 +#: .\opds_catalog\tests\test_feeds.py:104 +#: .\opds_catalog\tests\test_feeds.py:117 +#: .\opds_catalog\tests\test_feeds.py:128 +msgid "Cyrillic" +msgstr "Кириллица (РУС)" + +#: .\opds_catalog\feeds.py:723 .\opds_catalog\models.py:16 +#: .\opds_catalog\tests\test_feeds.py:105 +msgid "Latin" +msgstr "Латинница (LAT)" + +#: .\opds_catalog\feeds.py:724 .\opds_catalog\models.py:16 +#: .\opds_catalog\tests\test_feeds.py:106 +msgid "Digits" +msgstr "Цифры (0..9)" + +#: .\opds_catalog\feeds.py:725 .\opds_catalog\models.py:16 +#: .\opds_catalog\tests\test_feeds.py:107 +msgid "Other symbols" +msgstr "Другие символы" + +#: .\opds_catalog\feeds.py:726 .\opds_catalog\models.py:16 +#: .\opds_catalog\tests\test_feeds.py:108 +msgid "Show all" +msgstr "Показать все" + +#: .\opds_catalog\feeds.py:757 +msgid "Select books by substring" +msgstr "Поиск книг по подстроке" + +#: .\opds_catalog\feeds.py:794 .\opds_catalog\feeds.py:962 +#, python-format +msgid "Found: %s books" +msgstr "Найдено %s книг" + +#: .\opds_catalog\feeds.py:816 +msgid "Select authors by substring" +msgstr "Поиск авторов по подстроке" + +#: .\opds_catalog\feeds.py:853 +#, python-format +msgid "Found: %s authors" +msgstr "Найдено %s авторов" + +#: .\opds_catalog\feeds.py:875 +msgid "Select series by substring" +msgstr "Поиск серий по подстроке" + +#: .\opds_catalog\feeds.py:912 +#, python-format +msgid "Found: %s series" +msgstr "Найдено %s серий" + +#: .\opds_catalog\feeds.py:933 +#, python-format +msgid "Select genres (%s)" +msgstr "Выбор жанра (%s)" + +#: .\opds_catalog\feeds.py:933 +msgid "section" +msgstr "секция" + +#: .\opds_catalog\feeds.py:933 +msgid "subsection" +msgstr "подсекция" + +#: .\opds_catalog\templates\book_description.html:7 +#: .\opds_catalog\templates\book_description_cat.html:7 +msgid "Book name:" +msgstr "Название:" + +#: .\opds_catalog\templates\book_description.html:8 +#: .\opds_catalog\templates\book_description_cat.html:8 +msgid "Authors:" +msgstr "Авторы:" + +#: .\opds_catalog\templates\book_description.html:9 +#: .\opds_catalog\templates\book_description_cat.html:9 +msgid "Genres:" +msgstr "Жанры:" + +#: .\opds_catalog\templates\book_description.html:10 +#: .\opds_catalog\templates\book_description_cat.html:10 +#, fuzzy +#| msgid "Genres:" +msgid "Series:" +msgstr "Жанры:" + +#: .\opds_catalog\templates\book_description.html:11 +#: .\opds_catalog\templates\book_description_cat.html:11 +msgid "File:" +msgstr "Файл:" + +#: .\opds_catalog\templates\book_description.html:12 +#: .\opds_catalog\templates\book_description_cat.html:12 +msgid "File size:" +msgstr "Размер файла:" + +#: .\opds_catalog\templates\book_description.html:13 +#: .\opds_catalog\templates\book_description_cat.html:13 +msgid "Changes date:" +msgstr "Дата правки:" + +#: .\opds_catalog\templates\book_description.html:14 +msgid "Doubles count:" +msgstr "Число дубликатов:" diff --git a/opds_catalog/log/emptyfile b/opds_catalog/log/emptyfile new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opds_catalog/management/commands/__pycache__/server.cpython-35.pyc b/opds_catalog/management/commands/__pycache__/server.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0baf7067acea5d5f802af772e2decca3feac9556 Binary files /dev/null and b/opds_catalog/management/commands/__pycache__/server.cpython-35.pyc differ diff --git a/opds_catalog/management/commands/__pycache__/sopds.cpython-35.pyc b/opds_catalog/management/commands/__pycache__/sopds.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7585fe0420952a7dbf1bbec35577350059b0279b Binary files /dev/null and b/opds_catalog/management/commands/__pycache__/sopds.cpython-35.pyc differ diff --git a/opds_catalog/management/commands/__pycache__/sopds_scanner.cpython-35.pyc b/opds_catalog/management/commands/__pycache__/sopds_scanner.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd7d1140918622e50258ab9ffadacb23ab070094 Binary files /dev/null and b/opds_catalog/management/commands/__pycache__/sopds_scanner.cpython-35.pyc differ diff --git a/opds_catalog/management/commands/__pycache__/sopds_server.cpython-35.pyc b/opds_catalog/management/commands/__pycache__/sopds_server.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccbaedcd27de004cffdc7fede4724a0dd8e557a3 Binary files /dev/null and b/opds_catalog/management/commands/__pycache__/sopds_server.cpython-35.pyc differ diff --git a/opds_catalog/management/commands/__pycache__/sopds_util.cpython-35.pyc b/opds_catalog/management/commands/__pycache__/sopds_util.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c73fc7e4d81c96cae3fb5c40847366cda3c119c8 Binary files /dev/null and b/opds_catalog/management/commands/__pycache__/sopds_util.cpython-35.pyc differ diff --git a/opds_catalog/management/commands/sopds_scanner.py b/opds_catalog/management/commands/sopds_scanner.py new file mode 100644 index 0000000000000000000000000000000000000000..5b0a10f739fa235439f8a4c16930704f38718f9e --- /dev/null +++ b/opds_catalog/management/commands/sopds_scanner.py @@ -0,0 +1,134 @@ +import os +import signal +import sys +import logging + +from apscheduler.schedulers.blocking import BlockingScheduler + +from django.core.management.base import BaseCommand +from django.db import transaction +from django.conf import settings + +from opds_catalog.models import Counter +from opds_catalog.sopdscan import opdsScanner +from opds_catalog.settings import SCANNER_LOG, SCAN_SHED_DAY, SCAN_SHED_DOW, SCAN_SHED_HOUR, SCAN_SHED_MIN, LOGLEVEL, SCANNER_PID + +class Command(BaseCommand): + help = 'Scan Books Collection.' + + def add_arguments(self, parser): + parser.add_argument('command', help='Use [ scan | start | stop | restart ]') + parser.add_argument('--verbose',action='store_true', dest='verbose', default=False, help='Set verbosity level for books collection scan.') + parser.add_argument('--daemon',action='store_true', dest='daemonize', default=False, help='Daemonize server') + + def handle(self, *args, **options): + self.pidfile = os.path.join(settings.BASE_DIR, SCANNER_PID) + action = options['command'] + self.logger = logging.getLogger('') + self.logger.setLevel(logging.DEBUG) + formatter=logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') + + if LOGLEVEL!=logging.NOTSET: + # Создаем обработчик для записи логов в файл + fh = logging.FileHandler(SCANNER_LOG) + fh.setLevel(LOGLEVEL) + fh.setFormatter(formatter) + self.logger.addHandler(fh) + + if options['verbose']: + # Создадим обработчик для вывода логов на экран с максимальным уровнем вывода + ch = logging.StreamHandler() + ch.setLevel(logging.DEBUG) + ch.setFormatter(formatter) + self.logger.addHandler(ch) + + if (options["daemonize"] and (action in ["start", "scan"])): + if sys.platform == "win32": + self.stdout.write("On Windows platform Daemonize not working.") + else: + daemonize() + + if action=='scan': + self.stdout.write('Startup once book-scan.') + self.scan() + self.stdout.write('Complete book-scan.') + elif action == "start": + self.start() + elif action == "stop": + pid = open(self.pidfile, "r").read() + self.stop(pid) + elif action == "restart": + pid = open(self.pidfile, "r").read() + self.restart(pid) + + def scan(self): + scanner=opdsScanner(self.logger) + with transaction.atomic(): + scanner.scan_all() + Counter.objects.update_known_counters() + + def start(self): + writepid(self.pidfile) + self.stdout.write('Startup scheduled book-scan (min=%s, hour=%s, day_of_week=%s, day=%s).'%(SCAN_SHED_MIN,SCAN_SHED_HOUR,SCAN_SHED_DOW,SCAN_SHED_DAY)) + sched = BlockingScheduler() + sched.add_job(self.scan, 'cron', day=SCAN_SHED_DAY, day_of_week=SCAN_SHED_DOW, hour=SCAN_SHED_HOUR, minute=SCAN_SHED_MIN) + quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-C' + self.stdout.write("Quit the server with %s.\n"%quit_command) + try: + sched.start() + except (KeyboardInterrupt, SystemExit): + pass + + def stop(self, pid): + try: + os.kill(int(pid), signal.SIGTERM) + except OSError as e: + self.stdout.write("Error stopping sopds_scanner: %s"%str(e)) + + def restart(self, pid): + self.stop(pid) + self.start() + +def writepid(pid_file): + """ + Write the process ID to disk. + """ + fp = open(pid_file, "w") + fp.write(str(os.getpid())) + fp.close() + +def daemonize(): + """ + Detach from the terminal and continue as a daemon. + """ + # swiped from twisted/scripts/twistd.py + # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16 + if os.fork(): # launch child and... + os._exit(0) # kill off parent + os.setsid() + if os.fork(): # launch child and... + os._exit(0) # kill off parent again. + os.umask(0) + + std_in = open("/dev/null", 'r') + std_out = open(SCANNER_LOG, 'a+') + os.dup2(std_in.fileno(), sys.stdin.fileno()) + os.dup2(std_out.fileno(), sys.stdout.fileno()) + os.dup2(std_out.fileno(), sys.stderr.fileno()) + +# null = os.open("/dev/null", os.O_RDWR) +# for i in range(3): +# try: +# os.dup2(null, i) +# except OSError as e: +# if e.errno != errno.EBADF: +# raise + os.close(std_in.fileno()) + os.close(std_out.fileno()) + + + + + + + diff --git a/opds_catalog/management/commands/sopds_server.py b/opds_catalog/management/commands/sopds_server.py new file mode 100644 index 0000000000000000000000000000000000000000..dceee88d0cd2658f76e0ba2e91045904527f4cf3 --- /dev/null +++ b/opds_catalog/management/commands/sopds_server.py @@ -0,0 +1,93 @@ +import os +import signal +import sys + +from django.conf import settings +from django.core.management.base import BaseCommand +from django.core.management import call_command + +from opds_catalog.settings import SERVER_LOG, SERVER_PID + +class Command(BaseCommand): + help = 'HTTP/OPDS built-in server' + + def add_arguments(self, parser): + parser.add_argument('command', help='Use [ start | stop | restart ]') + parser.add_argument('--host',action='store', dest='host', default="0.0.0.0", help='Set server binding address') + parser.add_argument('--port',action='store', dest='port', default=8001, help='Set server port') + parser.add_argument('--daemon',action='store_true', dest='daemonize', default=False, help='Daemonize server') + + + def handle(self, *args, **options): + self.pidfile = os.path.join(settings.BASE_DIR, SERVER_PID) + action = options['command'] + self.addr = options['host'] + self.port = int(options['port']) + + if (options["daemonize"] and (action == "start")): + if sys.platform == "win32": + self.stdout.write("On Windows platform Daemonize not working.") + else: + daemonize() + + if action == "start": + self.start() + elif action == "stop": + pid = open(self.pidfile, "r").read() + self.stop(pid) + elif action == "restart": + pid = open(self.pidfile, "r").read() + self.restart(pid) + + def start(self): + writepid(self.pidfile) + call_command('runserver',addrport='%s:%s'%(self.addr,self.port), use_reloader=False, app_label='opds_catalog') + + def stop(self, pid): + try: + os.kill(int(pid), signal.SIGTERM) + except OSError as e: + self.stdout.write("Error stopping sopds_server: %s"%str(e)) + + def restart(self, pid): + self.stop(pid) + self.start() + +def writepid(pid_file): + """ + Write the process ID to disk. + """ + fp = open(pid_file, "w") + fp.write(str(os.getpid())) + fp.close() + +def daemonize(): + """ + Detach from the terminal and continue as a daemon. + """ + # swiped from twisted/scripts/twistd.py + # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16 + if os.fork(): # launch child and... + os._exit(0) # kill off parent + os.setsid() + if os.fork(): # launch child and... + os._exit(0) # kill off parent again. + os.umask(0) + + std_in = open("/dev/null", 'r') + std_out = open(SERVER_LOG, 'a+') + os.dup2(std_in.fileno(), sys.stdin.fileno()) + os.dup2(std_out.fileno(), sys.stdout.fileno()) + os.dup2(std_out.fileno(), sys.stderr.fileno()) + +# null = os.open("/dev/null", os.O_RDWR) +# for i in range(3): +# try: +# os.dup2(null, i) +# except OSError as e: +# if e.errno != errno.EBADF: +# raise + os.close(std_in.fileno()) + os.close(std_out.fileno()) + + diff --git a/opds_catalog/management/commands/sopds_util.py b/opds_catalog/management/commands/sopds_util.py new file mode 100644 index 0000000000000000000000000000000000000000..990985f72d6261f1a4ee0debd6916bae4b8bad49 --- /dev/null +++ b/opds_catalog/management/commands/sopds_util.py @@ -0,0 +1,21 @@ +from django.core.management.base import BaseCommand +from django.core.management import call_command +from opds_catalog import opdsdb +from opds_catalog.models import Counter + +class Command(BaseCommand): + help = 'Utils for SOPDS.' + + def add_arguments(self, parser): + parser.add_argument('--clear',action='store_true', dest='clear', default=False, help='Clear opds database.') + + def handle(self, *args, **options): + if options['clear']: + self.stdout.write('Clear book database.') + self.clear() + + def clear(self): + opdsdb.clear_all() + call_command('loaddata', 'genre.json', app_label='opds_catalog') + Counter.objects.update_known_counters() + diff --git a/opds_catalog/migrations/0001_initial.py b/opds_catalog/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..6fb08dd413847444079ba422a85687a4a46e1566 --- /dev/null +++ b/opds_catalog/migrations/0001_initial.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-08-13 18:01 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Author', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('first_name', models.CharField(max_length=64)), + ('last_name', models.CharField(max_length=64)), + ('lang_code', models.IntegerField(db_index=True, default=9)), + ], + ), + migrations.CreateModel( + name='bauthor', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Author')), + ], + ), + migrations.CreateModel( + name='bgenre', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + ), + migrations.CreateModel( + name='Book', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('filename', models.CharField(db_index=True, max_length=256)), + ('path', models.CharField(db_index=True, max_length=1024)), + ('filesize', models.IntegerField(default=0)), + ('format', models.CharField(max_length=8)), + ('cat_type', models.IntegerField(default=0)), + ('registerdate', models.DateTimeField(db_index=True, default=django.utils.timezone.now)), + ('docdate', models.CharField(max_length=20)), + ('lang', models.CharField(max_length=16)), + ('title', models.CharField(max_length=256)), + ('annotation', models.CharField(max_length=10000)), + ('lang_code', models.IntegerField(db_index=True, default=9)), + ('avail', models.IntegerField(default=0)), + ('authors', models.ManyToManyField(through='opds_catalog.bauthor', to='opds_catalog.Author')), + ], + ), + migrations.CreateModel( + name='bookshelf', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('readtime', models.DateTimeField(default=django.utils.timezone.now)), + ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Book')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='bseries', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ser_no', models.IntegerField(default=0)), + ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Book')), + ], + ), + migrations.CreateModel( + name='Catalog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cat_name', models.CharField(max_length=64)), + ('path', models.CharField(max_length=1024)), + ('cat_type', models.IntegerField(default=0)), + ('parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Catalog')), + ], + ), + migrations.CreateModel( + name='Counter', + fields=[ + ('name', models.CharField(max_length=16, primary_key=True, serialize=False)), + ('value', models.IntegerField(default=0)), + ('update_time', models.DateTimeField(default=django.utils.timezone.now)), + ], + ), + migrations.CreateModel( + name='Genre', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('genre', models.CharField(db_index=True, max_length=32)), + ('section', models.CharField(max_length=64)), + ('subsection', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='Series', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ser', models.CharField(db_index=True, max_length=64)), + ('lang_code', models.IntegerField(db_index=True, default=9)), + ], + ), + migrations.AddField( + model_name='bseries', + name='ser', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Series'), + ), + migrations.AddField( + model_name='book', + name='catalog', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Catalog'), + ), + migrations.AddField( + model_name='book', + name='genres', + field=models.ManyToManyField(through='opds_catalog.bgenre', to='opds_catalog.Genre'), + ), + migrations.AddField( + model_name='book', + name='series', + field=models.ManyToManyField(through='opds_catalog.bseries', to='opds_catalog.Series'), + ), + migrations.AddField( + model_name='bgenre', + name='book', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Book'), + ), + migrations.AddField( + model_name='bgenre', + name='genre', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Genre'), + ), + migrations.AddField( + model_name='bauthor', + name='book', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='opds_catalog.Book'), + ), + migrations.AlterIndexTogether( + name='author', + index_together=set([('last_name', 'first_name')]), + ), + migrations.AlterIndexTogether( + name='catalog', + index_together=set([('cat_name', 'path')]), + ), + migrations.AlterIndexTogether( + name='bseries', + index_together=set([('book', 'ser')]), + ), + migrations.AlterIndexTogether( + name='book', + index_together=set([('title', 'format', 'filesize'), ('avail',)]), + ), + migrations.AlterIndexTogether( + name='bgenre', + index_together=set([('book', 'genre')]), + ), + migrations.AlterIndexTogether( + name='bauthor', + index_together=set([('book', 'author')]), + ), + ] diff --git a/opds_catalog/migrations/0002_auto_20161102_2132.py b/opds_catalog/migrations/0002_auto_20161102_2132.py new file mode 100644 index 0000000000000000000000000000000000000000..cf66633cacbc14c63349617f5e72866704095eec --- /dev/null +++ b/opds_catalog/migrations/0002_auto_20161102_2132.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.2 on 2016-11-02 18:32 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.manager + + +class Migration(migrations.Migration): + + dependencies = [ + ('opds_catalog', '0001_initial'), + ] + + operations = [ + migrations.AlterModelManagers( + name='counter', + managers=[ + ('obj', django.db.models.manager.Manager()), + ], + ), + migrations.AlterField( + model_name='book', + name='docdate', + field=models.CharField(max_length=32), + ), + migrations.AlterField( + model_name='catalog', + name='cat_name', + field=models.CharField(max_length=128), + ), + migrations.AlterField( + model_name='series', + name='ser', + field=models.CharField(db_index=True, max_length=80), + ), + ] diff --git a/opds_catalog/migrations/__init__.py b/opds_catalog/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opds_catalog/migrations/__pycache__/0001_initial.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0001_initial.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe897e18f97c177dcfa4c1d2a373a15f2308f34e Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0001_initial.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/0002_auto_20161102_2132.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0002_auto_20161102_2132.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0191127d956f99470dc87df0a2ce73f296ad1acb Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0002_auto_20161102_2132.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/0002_counters.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0002_counters.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..878089b6730699fd8028ffc1223a54c092f722ca Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0002_counters.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/0003_auto_20160320_1724.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0003_auto_20160320_1724.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e580a4680352965840b5c49c8080c89da9c3f2e Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0003_auto_20160320_1724.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/0004_auto_20160320_1741.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0004_auto_20160320_1741.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..276eca857880b7cb93b58cc26ebc8f68841cea92 Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0004_auto_20160320_1741.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/0005_auto_20160718_2013.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0005_auto_20160718_2013.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..af43ec7061f97e273fb16b454e0b65346e0b1d7f Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0005_auto_20160718_2013.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/0006_auto_20160718_2025.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0006_auto_20160718_2025.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe86722ca677646c4bf2af2d6405e6ffa7547ef1 Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0006_auto_20160718_2025.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/0007_auto_20160813_2043.cpython-35.pyc b/opds_catalog/migrations/__pycache__/0007_auto_20160813_2043.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ec0e8afaafc91d83699842ab9195d297086a201 Binary files /dev/null and b/opds_catalog/migrations/__pycache__/0007_auto_20160813_2043.cpython-35.pyc differ diff --git a/opds_catalog/migrations/__pycache__/__init__.cpython-35.pyc b/opds_catalog/migrations/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..958251028dcab692bb5c11d201548d76126815d7 Binary files /dev/null and b/opds_catalog/migrations/__pycache__/__init__.cpython-35.pyc differ diff --git a/opds_catalog/models.py b/opds_catalog/models.py new file mode 100644 index 0000000000000000000000000000000000000000..dad2c633916eebc92dbcce041f2e98f6760e8268 --- /dev/null +++ b/opds_catalog/models.py @@ -0,0 +1,136 @@ +from django.db import models +from django.contrib.auth.models import User +from django.utils import timezone +from django.core.exceptions import ObjectDoesNotExist +from django.utils.translation import ugettext as _ + +counter_allbooks = 'allbooks' +counter_allcatalogs = 'allcatalogs' +counter_allauthors = 'allauthors' +counter_allgenres = 'allgenres' +counter_allseries = 'allseries' + +LangCodes = {1:'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзийклмнопрстуфхцчшщьыъэюя', + 2:'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', + 3:'0123456789'} +lang_menu = {1:_('Cyrillic'), 2:_('Latin'), 3:_('Digits'), 9:_('Other symbols'), 0:_('Show all')} + +class Book(models.Model): + filename = models.CharField(db_index=True, max_length=256) + path = models.CharField(db_index=True, max_length=1024) + filesize = models.IntegerField(null=False, default=0) + format = models.CharField(max_length=8) + catalog = models.ForeignKey('Catalog',db_index=True) + cat_type = models.IntegerField(null=False, default=0) + registerdate = models.DateTimeField(db_index=True, null=False, default=timezone.now) + docdate = models.CharField(max_length=32) + #favorite = models.IntegerField(null=False, default=0) + lang = models.CharField(max_length=16) + title = models.CharField(max_length=256) + annotation = models.CharField(max_length=10000) + #cover = models.CharField(max_length=32) + #cover_type = models.CharField(max_length=32) + #doublicat = models.IntegerField(null=False, default=0) + lang_code = models.IntegerField(db_index=True, null=False, default=9) + avail = models.IntegerField(null=False, default=0) + authors = models.ManyToManyField('Author', through='bauthor') + genres = models.ManyToManyField('Genre', through='bgenre') + series = models.ManyToManyField('Series', through='bseries') + + class Meta: + index_together = [ + ["title", "format", "filesize"], + ["avail"], + ] + +class Catalog(models.Model): + parent = models.ForeignKey('self', null=True) + cat_name = models.CharField(max_length=128) + path = models.CharField(max_length=1024) + cat_type = models.IntegerField(null=False, default=0) + + class Meta: + index_together = [ + ["cat_name", "path"], + ] + +class Author(models.Model): + first_name = models.CharField(max_length=64) + last_name = models.CharField(max_length=64) + lang_code = models.IntegerField(db_index=True, null=False, default=9) + + class Meta: + index_together = [ + ["last_name", "first_name"], + ] + +class bauthor(models.Model): + book = models.ForeignKey('Book') + author = models.ForeignKey('Author') + class Meta: + index_together = [ + ["book", "author"], + ] + +class Genre(models.Model): + genre = models.CharField(db_index=True, max_length=32) + section = models.CharField(max_length=64) + subsection = models.CharField(max_length=100) + +class bgenre(models.Model): + book = models.ForeignKey('Book') + genre = models.ForeignKey('Genre') + + class Meta: + index_together = [ + ["book", "genre"], + ] + +class Series(models.Model): + ser = models.CharField(db_index=True, max_length=80) + lang_code = models.IntegerField(db_index=True, null=False, default=9) + +class bseries(models.Model): + book = models.ForeignKey('Book') + ser = models.ForeignKey('Series') + ser_no = models.IntegerField(null=False, default=0) + + class Meta: + index_together = [ + ["book", "ser"], + ] + +class bookshelf(models.Model): + user = models.ForeignKey(User) + book = models.ForeignKey(Book) + readtime = models.DateTimeField(null=False, default=timezone.now) + + +class CounterManager(models.Manager): + def update(self, counter_name, counter_value): + self.update_or_create(name=counter_name, defaults = {"value":counter_value, "update_time":timezone.now()}) + + def update_known_counters(self): + self.update(counter_allbooks, Book.objects.all().count()) + self.update(counter_allcatalogs, Catalog.objects.all().count()) + self.update(counter_allauthors, Author.objects.all().count()) + self.update(counter_allgenres, Genre.objects.all().count()) + self.update(counter_allseries, Series.objects.all().count()) + + def get_counter(self, counter_name): + try: + counter = self.get(name=counter_name).value + except ObjectDoesNotExist: + counter = 0 + + return counter + +class Counter(models.Model): + name = models.CharField(primary_key=True, null=False, blank=False, max_length=16) + value = models.IntegerField(null=False, default=0) + update_time = models.DateTimeField(null=False, default=timezone.now) + obj = models.Manager() + objects = CounterManager() + + + diff --git a/opds_catalog/opds_middleware.py b/opds_catalog/opds_middleware.py new file mode 100644 index 0000000000000000000000000000000000000000..b8f9e151c2f4bca9d0986bab63e7656b8c2580a1 --- /dev/null +++ b/opds_catalog/opds_middleware.py @@ -0,0 +1,50 @@ +import base64 + +from django.http import HttpResponse +from django.contrib import auth +from django.core.exceptions import ImproperlyConfigured +from django.core.urlresolvers import resolve + +from opds_catalog import settings + + +class BasicAuthMiddleware(object): + header = "HTTP_AUTHORIZATION" + + def unauthed(self): + response = HttpResponse("""Auth required +

Authorization Required

""", content_type="text/html") + response['WWW-Authenticate'] = 'Basic realm="OPDS"' + response.status_code = 401 + return response + + def process_request(self,request): + if not settings.AUTH: + return + + # AuthenticationMiddleware is required so that request.user exists. + if not hasattr(request, 'user'): + raise ImproperlyConfigured( + "The Django remote user auth middleware requires the" + " authentication middleware to be installed. Edit your" + " MIDDLEWARE setting to insert" + " 'django.contrib.auth.middleware.AuthenticationMiddleware'" + " before the BasicAuthMiddleware class.") + try: + authentication = request.META[self.header] + except KeyError: + return self.unauthed() + + (auth_meth, auth_data) = authentication.split(' ',1) + if 'basic' != auth_meth.lower(): + return self.unauthed() + auth_data = base64.b64decode(auth_data.strip()).decode('utf-8') + username, password = auth_data.split(':',1) + + user = auth.authenticate(username=username, password=password) + if user and user.is_active: + request.user = user + auth.login(request, user) + return + + return self.unauthed() \ No newline at end of file diff --git a/opds_catalog/opdsdb.py b/opds_catalog/opdsdb.py new file mode 100644 index 0000000000000000000000000000000000000000..7cf6935587a2fc4ff254962e9cbedb36093fc253 --- /dev/null +++ b/opds_catalog/opdsdb.py @@ -0,0 +1,159 @@ +import os + +from django.db.models import Q + +from opds_catalog.models import Book, Catalog, Author, Genre, Series, bseries, bauthor, bgenre, bookshelf, Counter, LangCodes + +########################################################################## +# типы каталогов (cat_type) +# +CAT_NORMAL=0 +CAT_ZIP=1 +CAT_GZ=2 + +########################################################################## +# Как будем искать дубликаты +# +CMP_NONE=0 +CMP_NORMAL=1 +CMP_STRONG=2 +CMP_CLEAR=3 +CMP_TITLE_FTYPE_FSIZE=2 +CMP_TITLE_AUTHORS=1 + +########################################################################## +# разные константы +# +unknown_genre='Неизвестный жанр' + + +def clear_all(): + Book.objects.all().delete() + Catalog.objects.all().delete() + Author.objects.all().delete() + Genre.objects.all().delete() + Series.objects.all().delete() + bseries.objects.all().delete() + bauthor.objects.all().delete() + bseries.objects.all().delete() + bookshelf.objects.all().delete() + Counter.objects.all().delete() + +# Книги где avail=0 уже известно что удалены +# Книги где avail=2 это только что прверенные существующие книги +# Устанавливаем avail=1 для книг которые не удалены. Во время проверки +# если они не удалены им присвоится значение 2 +# Книги с avail=0 проверятся не будут и будут убраны из всех выдач и всех обработок. +# +# три позиции (0,1,2) сделаны для того чтобы сделать возможным корректную работу +# cgi-скрипта во время сканирования библиотеки +# +def getlangcode(s): + langcode = 9 + if len(s)==0: + return langcode + for k in LangCodes.keys(): + if s[0] in LangCodes[k]: + langcode = k + + return langcode + +def avail_check_prepare(): + Book.objects.filter(~Q(avail=0)).update(avail=1) + +def books_del_logical(): + row_count = Book.objects.filter(avail=1).update(avail=0) + return row_count + +def books_del_phisical(): + row_count = Book.objects.filter(avail__lte=1).delete() + # TODO: Разобратся нужно ли удалять записи в таблицах связи ManyToMany или они сами удалятся? + # sql='delete from '+TBL_BAUTHORS+' where book_id in (select book_id from '+TBL_BOOKS+' where avail<=1)' + # sql='delete from '+TBL_BGENRES+' where book_id in (select book_id from '+TBL_BOOKS+' where avail<=1)' + return row_count + +def zipisscanned(zipname,setavail=0): + row_count = Book.objects.filter(path=zipname).update(avail=2) + return row_count + +def findcat(cat_name): + (head,tail)=os.path.split(cat_name) + try: + catalog = Catalog.objects.get(cat_name=tail, path=cat_name) + except Catalog.DoesNotExist: + catalog = None + + return catalog + +def addcattree(cat_name, archive=0): + catalog = findcat(cat_name) + if catalog: + return catalog + if cat_name in ("","."): + return Catalog.objects.get_or_create(parent=None, cat_name=".", path=".", cat_type=0)[0] + (head,tail)=os.path.split(cat_name) + parent=addcattree(head) + new_cat = Catalog.objects.create(parent=parent, cat_name=tail, path=cat_name, cat_type=archive) + + return new_cat + +def findbook(name, path, setavail=0): + # Здесь специально не делается проверка avail, т.к. если удаление было логическим, + # а книга была восстановлена в своем старом месте + # то произойдет восстановление записи об этой книги а не добавится новая + try: + book = Book.objects.get(filename=name, path=path) + except Book.DoesNotExist: + book = None + + if book and setavail: + book.avail=2 + book.save() + + return book + +def addbook(name, path, cat, exten, title, annotation, docdate, lang, size=0, archive=0): + format=exten[1:] + format=format.lower() + book = Book.objects.create(filename=name,path=path,catalog=cat,filesize=size,format=format, + title=title,annotation=annotation,docdate=docdate,lang=lang, + cat_type=archive,avail=2, lang_code=getlangcode(title)) + return book + +def findauthor(first_name,last_name): + try: + author = Author.objects.filter(last_name=last_name, first_name=first_name)[:1] + except Author.DoesNotExist: + author = None + + return author + +def addauthor(first_name, last_name): + author, created = Author.objects.get_or_create(last_name=last_name, first_name=first_name, lang_code=getlangcode(last_name)) + return author + +def addbauthor(book, author): + ba = bauthor(book=book, author=author) + ba.save() + #book.authors.add(author) + +def addgenre(genre): + genre, created = Genre.objects.get_or_create(genre=genre, defaults={'section':unknown_genre, 'subsection':genre}) + return genre + +def addbgenre(book, genre): + bg = bgenre(book=book, genre=genre) + bg.save() + #book.genres.add(genre) + +def addseries(ser): + series, created = Series.objects.get_or_create(ser=ser, lang_code=getlangcode(ser)) + return series + +def addbseries(book, ser, ser_no): + bs = bseries(book=book, ser=ser, ser_no=ser_no) + bs.save() + +def commit(): + #self.cnx.commit() + pass \ No newline at end of file diff --git a/opds_catalog/settings.py b/opds_catalog/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..77624fc78aabf919f1f62c94d17a47f0038adb54 --- /dev/null +++ b/opds_catalog/settings.py @@ -0,0 +1,70 @@ +import logging +import os +from django.conf import settings + +loglevels={'debug':logging.DEBUG,'info':logging.INFO,'warning':logging.WARNING,'error':logging.ERROR,'critical':logging.CRITICAL,'none':logging.NOTSET} + +VERSION = "0.33b" + +# Main SOPDS Book Collection Directory +ROOT_LIB = getattr(settings, "SOPDS_ROOT_LIB", "books/") +BOOK_EXTENSIONS = getattr(settings, "SOPDS_BOOK_EXTESIONS", ['.pdf', '.djvu', '.fb2', '.epub']) + +# Количество выдаваемых строк на одну страницу +MAXITEMS = getattr(settings, "SOPDS_MAXITEMS", 60) +DOUBLES_HIDE = getattr(settings, "SOPDS_DOUBLES_HIDE", True) +FB2PARSE = getattr(settings, "SOPDS_FB2PARSE", True) +FB2HSIZE = getattr(settings, "SOPDS_FB2HSIZE", 0) +COVER_SHOW = getattr(settings, "SOPDS_COVER_SHOW", True) +ZIPSCAN = getattr(settings, "SOPDS_ZIPSCAN", True) +ZIPRESCAN = getattr(settings, "SOPDS_ZIPRESCAN", False) +ZIPCODEPAGE = getattr(settings, "SOPDS_ZIPCODEPAGE", "cp866") +DELETE_LOGICAL = getattr(settings, "SOPDS_DELETE_LOGICAL", False) +SPLITITEMS = getattr(settings, "SOPDS_SPLITITEMS", 300) +FB2TOEPUB = getattr(settings, "SOPDS_FB2TOEPUB", "") +FB2TOMOBI = getattr(settings, "SOPDS_FB2TOMOBI", "") +TEMP_DIR = getattr(settings, "SOPDS_TEMP_DIR", os.path.join(settings.BASE_DIR,'tmp')) +SINGLE_COMMIT = getattr(settings, "SOPDS_SINGLE_COMMIT", True) +TITLE_AS_FILENAME = getattr(settings, "SOPDS_TITLE_AS_FILENAME", True) +ALPHABET_MENU = getattr(settings, "SOPDS_ALPHABET_MENU", True) +NOCOVER_PATH = getattr(settings, "SOPDS_NOCOVER_PATH", os.path.join(settings.BASE_DIR,'static/images/nocover.jpg')) +AUTH = getattr(settings, "SOPDS_AUTH", False) +SERVER_LOG = getattr(settings, "SOPDS_SERVER_LOG", os.path.join(settings.BASE_DIR,'opds_cataog/log/sopds_server.log')) +SCANNER_LOG = getattr(settings, "SOPDS_SCANNER_LOG", os.path.join(settings.BASE_DIR,'opds_cataog/log/sopds_scanner.log')) +SERVER_PID = getattr(settings, "SOPDS_SERVER_PID", os.path.join(settings.BASE_DIR,'opds_cataog/tmp/sopds_server.pid')) +SCANNER_PID = getattr(settings, "SOPDS_SCANNER_PID", os.path.join(settings.BASE_DIR,'opds_cataog/tmp/sopds_scanner.pid')) +SCAN_SHED_MIN = getattr(settings, "SOPDS_SCAN_SHED_MIN", '0') +SCAN_SHED_HOUR = getattr(settings, "SOPDS_SCAN_SHED_HOUR", '0') +SCAN_SHED_DAY = getattr(settings, "SOPDS_SCAN_SHED_DAY", '*') +SCAN_SHED_DOW = getattr(settings, "SOPDS_SCAN_SHED_DOW", '*') + +TITLE = getattr(settings, "SOPDS_TITLE", "SimpleOPDS") +SUBTITLE = getattr(settings, "SOPDS_SUBTITLE", "SimpleOPDS Catalog by www.sopds.ru. Version %s."%VERSION) +ICON = getattr(settings, "SOPDS_ICON", "/static/images/favicon.ico") + +loglevel = getattr(settings, "SOPDS_LOGLEVEL", "info") +if loglevel.lower() in loglevels: + LOGLEVEL=loglevels[loglevel.lower()] +else: + LOGLEVEL=logging.NOTSET + +# Переопределяем некоторые функции для SQLite, которые работают неправлено +from django.db.backends.signals import connection_created +from django.dispatch import receiver + +def sopds_upper(s): + return s.upper() + +def sopds_substring(s,i,l): + i = i - 1 + return s[i:i+l] + +def sopds_concat(s1='',s2='',s3=''): + return "%s%s%s"%(s1,s2,s3) + +@receiver(connection_created) +def extend_sqlite(connection=None, **kwargs): + if connection.vendor == "sqlite": + connection.connection.create_function('upper',1,sopds_upper) + connection.connection.create_function('substring',3,sopds_substring) + connection.connection.create_function('concat',3,sopds_concat) diff --git a/opds_catalog/sopdscan.py b/opds_catalog/sopdscan.py new file mode 100644 index 0000000000000000000000000000000000000000..749cc3397bb41b2cb482d69aea0283dcd5a5cc8f --- /dev/null +++ b/opds_catalog/sopdscan.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- + +import os +import time +import datetime +import base64 +import opds_catalog.zipf as zipfile +import logging + +from opds_catalog import fb2parse, settings, opdsdb + + +class opdsScanner: + def __init__(self, logger=None): + self.fb2parser=None + self.init_parser() + + if logger: + self.logger = logger + else: + self.logger = logging.getLogger('') + self.logger.setLevel(logging.CRITICAL) + self.init_stats() + + def init_stats(self): + self.t1=datetime.timedelta(seconds=time.time()) + self.t2=self.t1 + self.t3=self.t1 + self.books_added = 0 + self.books_skipped = 0 + self.books_deleted = 0 + self.arch_scanned = 0 + self.arch_skipped = 0 + self.bad_archives = 0 + self.bad_books = 0 + self.books_in_archives = 0 + + def init_parser(self): + self.fb2parser=fb2parse.fb2parser(False) + + def log_options(self): + self.logger.info(' ***** Starting sopds-scan...') + self.logger.debug('OPTIONS SET') + if settings.ROOT_LIB!=None: self.logger.debug('root_lib = '+settings.ROOT_LIB) + if settings.FB2TOEPUB!=None: self.logger.debug('fb2toepub = '+settings.FB2TOEPUB) + if settings.FB2TOMOBI!=None: self.logger.debug('fb2tomobi = '+settings.FB2TOMOBI) + if settings.TEMP_DIR!=None: self.logger.debug('temp_dir = '+settings.TEMP_DIR) + + def log_stats(self): + self.t2=datetime.timedelta(seconds=time.time()) + self.logger.info('Books added : '+str(self.books_added)) + self.logger.info('Books skipped : '+str(self.books_skipped)) + self.logger.info('Bad books : '+str(self.bad_books)) + if settings.DELETE_LOGICAL: + self.logger.info('Books deleted : '+str(self.books_deleted)) + else: + self.logger.info('Books DB entries deleted : '+str(self.books_deleted)) + self.logger.info('Books in archives: '+str(self.books_in_archives)) + self.logger.info('Archives scanned : '+str(self.arch_scanned)) + self.logger.info('Archives skipped : '+str(self.arch_skipped)) + self.logger.info('Bad archives : '+str(self.bad_archives)) + + t=self.t2-self.t1 + seconds=t.seconds%60 + minutes=((t.seconds-seconds)//60)%60 + hours=t.seconds//3600 + self.logger.info('Time estimated:'+str(hours)+' hours, '+str(minutes)+' minutes, '+str(seconds)+' seconds.') + + def scan_all(self): + self.init_stats() + self.log_options() + + opdsdb.avail_check_prepare() + + for full_path, dirs, files in os.walk(settings.ROOT_LIB, followlinks=True): + for name in files: + file=os.path.join(full_path,name) + (n,e)=os.path.splitext(name) + if (e.lower() == '.zip'): + if settings.ZIPSCAN: + self.processzip(name,full_path,file) + else: + file_size=os.path.getsize(file) + self.processfile(name,full_path,file,None,0,file_size) + + opdsdb.commit() + + if settings.DELETE_LOGICAL: + self.books_deleted=opdsdb.books_del_logical() + else: + self.books_deleted=opdsdb.books_del_phisical() + self.log_stats() + + def processzip(self,name,full_path,file): + rel_file=os.path.relpath(file,settings.ROOT_LIB) + if settings.ZIPRESCAN or (not opdsdb.zipisscanned(rel_file,1)): + zip_process_error = 0 + try: + z = zipfile.ZipFile(file, 'r', allowZip64=True) + filelist = z.namelist() + cat = opdsdb.addcattree(rel_file, 1) + for n in filelist: + try: + self.logger.debug('Start process ZIP file = '+file+' book file = '+n) + file_size=z.getinfo(n).file_size + self.processfile(n,file,z.open(n),cat,1,file_size) + except zipfile.BadZipFile: + self.logger.warning('Error processing ZIP file = '+file+' book file = '+n) + zip_process_error = 1 + z.close() + self.arch_scanned+=1 + except zipfile.BadZipFile: + self.logger.warning('Error while read ZIP archive. File '+file+' corrupt.') + zip_process_error = 1 + self.bad_archives+=zip_process_error + else: + self.arch_skipped+=1 + self.logger.debug('Skip ZIP archive '+rel_file+'. Already scanned.') + + def processfile(self,name,full_path,file,cat,archive=0,file_size=0): + (n,e)=os.path.splitext(name) + if e.lower() in settings.BOOK_EXTENSIONS: + rel_path=os.path.relpath(full_path,settings.ROOT_LIB) + self.logger.debug("Attempt to add book "+rel_path+"/"+name) + #self.logger.debug(" full_path = "+full_path) + #self.logger.debug(" settings.ROOT_LIB = "+settings.ROOT_LIB) + #self.logger.debug(" rel_path = "+rel_path) + + self.fb2parser.reset() + if opdsdb.findbook(name,rel_path,1)==None: + if archive==0: + cat=opdsdb.addcattree(rel_path,archive) + title='' + lang='' + annotation='' + docdate='' + book_is_valid = True + + if e.lower()=='.fb2' and settings.FB2PARSE: + if isinstance(file, str): + f=open(file,'rb') + else: + f=file + self.fb2parser.parse(f,settings.FB2HSIZE) + f.close() + + if len(self.fb2parser.lang.getvalue())>0: + lang=self.fb2parser.lang.getvalue()[0].strip(' \'\"') + if len(self.fb2parser.book_title.getvalue())>0: + title=self.fb2parser.book_title.getvalue()[0].strip(' »«\'\"\&\n-.#\\\`') + if len(self.fb2parser.annotation.getvalue())>0: + annotation=('\n'.join(self.fb2parser.annotation.getvalue()))[:10000] + if len(self.fb2parser.docdate.getvalue())>0: + docdate=self.fb2parser.docdate.getvalue()[0].strip(); + + if self.fb2parser.parse_error!=0: + errormsg='' + self.logger.warning(rel_path+' - '+name+' fb2 parse error ['+errormsg+']') + book_is_valid = False + self.bad_books+=1 + + if book_is_valid: + if title=='': title=n + + book=opdsdb.addbook(name,rel_path,cat,e,title,annotation,docdate,lang,file_size,archive) + self.books_added+=1 + + if archive==1: + self.books_in_archives+=1 + self.logger.debug("Book "+rel_path+"/"+name+" Added ok.") + + idx=0 + for l in self.fb2parser.author_last.getvalue(): + last_name=l.strip(' \n\'\"\&-.#\\\`') + first_name=self.fb2parser.author_first.getvalue()[idx].strip(' \n\'\"\&-.#\\\`') + author=opdsdb.addauthor(first_name,last_name) + opdsdb.addbauthor(book,author) + idx+=1 + for l in self.fb2parser.genre.getvalue(): + opdsdb.addbgenre(book,opdsdb.addgenre(l.lower().strip(' \n\'\"'))) + for l in self.fb2parser.series.attrss: + ser_name=l.get('name') + if ser_name: + ser=opdsdb.addseries(ser_name.strip()) + sser_no=l.get('number','0').strip() + if sser_no.isdigit(): + ser_no=int(sser_no) + else: + ser_no=0 + opdsdb.addbseries(book,ser,ser_no) + + if not settings.SINGLE_COMMIT: + opdsdb.commit() + + else: + self.books_skipped+=1 + self.logger.debug("Book "+rel_path+"/"+name+" Already in DB.") diff --git a/opds_catalog/static/images/nocover.jpg b/opds_catalog/static/images/nocover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5fae8b701f12b915474bf5f1fbecb4b9f4be18aa Binary files /dev/null and b/opds_catalog/static/images/nocover.jpg differ diff --git a/opds_catalog/templates/book_description.html b/opds_catalog/templates/book_description.html new file mode 100644 index 0000000000000000000000000000000000000000..525c774423c084a4cc0ef272ea969f3e6e5671a3 --- /dev/null +++ b/opds_catalog/templates/book_description.html @@ -0,0 +1,17 @@ +{% load i18n %} + +{% autoescape off %} +{% if obj.cat_name %} + {{ obj.cat_name }} +{% else %} + {% trans "Book name:" %} {{ obj.title }}
+ {% if obj.authors %}{% trans "Authors:" %} {% for a in obj.authors %}{{ a.last_name }} {{ a.first_name }}; {% endfor %}
{% endif %} + {% if obj.genres %}{% trans "Genres:" %} {% for g in obj.genres %}{{ g.subsection }}; {% endfor %}
{% endif %} + {% if obj.series %}{% trans "Series:" %} {% for s in obj.series %}{{s.ser}}; {% endfor %}
{% endif %} + {% trans "File:" %} {{ obj.filename }}
+ {% trans "File size:" %} {{ obj.filesize }}
+ {% trans "Changes date:" %} {{ obj.docdate }}
+ {% if obj.doubles %}{% trans "Doubles count:" %} {{ obj.doubles }}
{% endif %} +

{{ obj.annotation }}

+{% endif %} +{% endautoescape %} diff --git a/opds_catalog/templates/book_description_cat.html b/opds_catalog/templates/book_description_cat.html new file mode 100644 index 0000000000000000000000000000000000000000..bb781b727322fd71fe5194e641f41ec6ace95158 --- /dev/null +++ b/opds_catalog/templates/book_description_cat.html @@ -0,0 +1,16 @@ +{% load i18n %} + +{% autoescape off %} +{% if obj.cat_name %} + {{ obj.cat_name }} +{% else %} + {% trans "Book name:" %} {{ obj.title }}
+ {% trans "Authors:" %} {% for a in obj.authors.all %}{{ a.last_name }} {{ a.first_name }}; {% endfor %}
+ {% trans "Genres:" %} {% for g in obj.genres.all %}{{ g.subsection }}; {% endfor %}
+ {% trans "Series:" %} {% for s in obj.series.all %}{{s.ser}}; {% endfor %}
+ {% trans "File:" %} {{ obj.filename }}
+ {% trans "File size:" %} {{ obj.filesize }}
+ {% trans "Changes date:" %} {{ obj.docdate }}
+

{{ obj.annotation }}

+{% endif %} +{% endautoescape %} diff --git a/opds_catalog/templates/opensearch.html b/opds_catalog/templates/opensearch.html new file mode 100644 index 0000000000000000000000000000000000000000..9383ed964e2c45e10b517b739ecf10942af436d4 --- /dev/null +++ b/opds_catalog/templates/opensearch.html @@ -0,0 +1,18 @@ +{% autoescape off %} + + + SimpleOPDS + SimpleOPDS + + http://www.sopds.ru/favicon.ico + + + + + open + false + * + UTF-8 + UTF-8 + +{% endautoescape %} \ No newline at end of file diff --git a/opds_catalog/tests/__init__.py b/opds_catalog/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opds_catalog/tests/__pycache__/__init__.cpython-35.pyc b/opds_catalog/tests/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65254a793a36d2d28dd1b2b0453eb586c99211cd Binary files /dev/null and b/opds_catalog/tests/__pycache__/__init__.cpython-35.pyc differ diff --git a/opds_catalog/tests/__pycache__/test_dl.cpython-35.pyc b/opds_catalog/tests/__pycache__/test_dl.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27f59e0b1d92427443d668f009e81082a2ed3ea7 Binary files /dev/null and b/opds_catalog/tests/__pycache__/test_dl.cpython-35.pyc differ diff --git a/opds_catalog/tests/__pycache__/test_feeds.cpython-35.pyc b/opds_catalog/tests/__pycache__/test_feeds.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff0138da4ead9d6d1a6c83285c5811221bdc1ca5 Binary files /dev/null and b/opds_catalog/tests/__pycache__/test_feeds.cpython-35.pyc differ diff --git a/opds_catalog/tests/__pycache__/test_models.cpython-35.pyc b/opds_catalog/tests/__pycache__/test_models.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b14c1708423486e674d68488f39c44735e1ca6bd Binary files /dev/null and b/opds_catalog/tests/__pycache__/test_models.cpython-35.pyc differ diff --git a/opds_catalog/tests/__pycache__/test_opdsdb.cpython-35.pyc b/opds_catalog/tests/__pycache__/test_opdsdb.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4651f48b1ee1d632f4c4c409616b03935cb77565 Binary files /dev/null and b/opds_catalog/tests/__pycache__/test_opdsdb.cpython-35.pyc differ diff --git a/opds_catalog/tests/__pycache__/test_parsers.cpython-35.pyc b/opds_catalog/tests/__pycache__/test_parsers.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fde552b9c37665c966dc12e58e66761bd73ce53 Binary files /dev/null and b/opds_catalog/tests/__pycache__/test_parsers.cpython-35.pyc differ diff --git a/opds_catalog/tests/__pycache__/test_scan.cpython-35.pyc b/opds_catalog/tests/__pycache__/test_scan.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8b077bf1b8e4b7f6ce6213c28ed8429aab47110 Binary files /dev/null and b/opds_catalog/tests/__pycache__/test_scan.cpython-35.pyc differ diff --git a/opds_catalog/tests/__pycache__/test_zipf.cpython-35.pyc b/opds_catalog/tests/__pycache__/test_zipf.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb4b332acdfb7f25d5e8b29ba3c9e272f523da5a Binary files /dev/null and b/opds_catalog/tests/__pycache__/test_zipf.cpython-35.pyc differ diff --git a/opds_catalog/tests/data/262001.fb2 b/opds_catalog/tests/data/262001.fb2 new file mode 100644 index 0000000000000000000000000000000000000000..bf08139b4bc1c1c4048dca4c2d6dadb9494caf47 --- /dev/null +++ b/opds_catalog/tests/data/262001.fb2 @@ -0,0 +1,8161 @@ +antiqueEllisPetersThe Sanctuary Sparrowencalibre 0.7.4230.1.201119565c35-b326-4242-84c9-24373cf45fda1.0 +
+

The Sanctuary Sparrow

+
+
+

Ellis Peters

+ +

The Seventh Chronicle of Brother Cadfael

+ +

v1.0 released in #bookz October 7, 2002

+v1.5 EBook Design Group December 06, 2002

+v2.0 December 31,2002

+
+
+

Contents

+ +

^

+ +

+ +Chapter One

Chapter Two

Chapter Three

Chapter Four

Chapter Five

Chapter Six

Chapter Seven

Chapter Eight

Chapter Nine

Chapter Ten

Chapter Eleven

Chapter Twelve

Chapter Thirteen

Chapter Fourteen

+
+
+

Chapter One

+ +

« ^ »

+ +

Friday midnight to Saturday morning

+ +

It began, +as the greatest of storms do begin, as a mere tremor in the air, a thread of +sound so distant and faint, yet so ominous, that the ear that was sharp enough +to catch it instantly pricked and shut out present sounds to strain after it +again, and interpret the warning. Brother Cadfael had a hare’s hearing, readily +alerted and sharply focused. He caught the quiver and bay, at this point surely +still on the far side of the bridge that crossed Severn from the town, and +stiffened into responsive stillness, braced to listen.

+ +

It could have been an innocent sound enough, or if not innocent of murderous +intent, at any rate natural, the distant voices of hunting owls, and the +predatory bark of a dog-fox prowling his nocturnal barony. Certainly the +ferocious note of the hunt sounded clearly in it to Cadfael’s ear. And even +Brother Anselm the precentor, wholly absorbed into his chanting of the office, +wavered and slipped off-key for an instant, and took up the cadence jealously, +composing his mind sternly to duty.

+ +

For there could not be anything in it to trouble the midnight rite of +Matins, here in this kindly spring, barely four weeks past Easter of the year +of Our Lord 1140, with Shrewsbury and all this region secure within the king’s +peace, whatever contentions raged farther south between king and empress, +cousins at odds for the throne. The winter had been hard indeed, but was +blessedly over, the sun had shone on Easter Day, and continued shining ever +since, with only light, scattered showers to confirm the blessing. Only +westward in Wales had there been heavy spring rains, swelling the river level. +The season promised well, the town enjoyed fair rule under a dour but just +sheriff, and defended stoutly by a sensible provost and council. In a time of +civil war, Shrewsbury and its shire had good cause to thank God and King +Stephen for relative order. Not here, surely, should the conventual peace of +Matins fear any disruption. And yet Brother Anselm, for one instant, had +faltered.

+ +

In the dim space of the choir, partially shut off from the nave of the +church by the parish altar and lit only by the constant lamp and the candles on +the high altar, the brothers in their stalls showed like carven copies, in this +twilight without age or youth, comeliness or homeliness, so many matched +shadows. The height of the vault, the solid stone of the pillars and walls, +took up the sound of Brother Anselm’s voice, and made of it a disembodied +magic, high in air. Beyond where the candlelight reached and shadows ended, +there was darkness, the night within, the night without. A benign night, mild, +still and silent.

+ +

Not quite silent. The tremor on the air became a faint, persistent murmur. +In the dimness under the rood loft, to the right of the entrance to the choir, +Abbot Radulfus stirred in his stall. To the left, Prior Robert’s habit rustled +briefly, with an effect of displeasure and reproof rather than uneasiness. The +merest ripple of disquiet shivered along the ranks of the brothers, and again +subsided.

+ +

But the sound was drawing nearer. Even before it grew so loud as to compel +notice there was no mistaking the anger in it, the menace and the dangerous +excitement, all the marks of the hunt. It sounded as if the pursuit had reached +the point where the van chasseours had run the quarry to exhaustion, and the +parfytours were closing in for the kill. Even at this distance it was clear +that some creature’s life was in peril.

+ +

The sound drew nearer now very rapidly, hard to ignore, though the precentor +continued valiantly leading his flock in the office, and raised his voice and +quickened his tempo to ride over the challenge. The younger brothers and +novices were shifting uneasily, even whispering, half stimulated, half +affrighted. The murmur had become a ferocious, muted howl, as if gigantic bees +were in swarm after an intruder. Even abbot and prior had leaned forward ready +to rise from their stalls, and were exchanging questioning looks in the +dimness.

+ +

With obstinate devotion Brother Anselm lifted the first phrase of Lauds. He +got no farther. At the west end of the church the unlatched leaf of the great +parish door was suddenly hurled open to crash against the wall, and something +unseen came hurtling and scrabbling and gasping down the length of the nave, +reeling and fumbling and fending itself off from wall and pillar, heaving at +breath as though run to death already.

+ +

They were on their feet, every man. The younger ones broke out in frightened +exclamation and wonder, nudging and wavering in doubt what to do. Abbot +Radulfus in his own domain was hampered by no such hesitation. He moved with +speed and force, plucked a candle from the nearest sconce, and went striding +out round the parish altar in great, loping strides that sent his gown billowing +out behind him. After him went Prior Robert, more tender of his dignity, and +therefore slower to reach the scene of need, and after Robert all the brothers +in jostling agitation. Before they reached the nave they were met by a great, +exultant bellow of triumph, and a rushing and scrambling of dozens of frenzied +bodies, as the hunt burst in at the west door after its prey.

+ +

Brother Cadfael, once well accustomed to night alarms by land and by sea, +had surged out of his stall as soon as the abbot moved, but took time to grasp +a double candelabrum to light his way. Prior Robert in full sail was already +blocking the right-hand way round the parish altar, too patrician to make +enough haste to ruffle his silvery beauty. Cadfael doubled round to the left and +emerged into the nave before him, with his light thrust out ahead, as much +weapon as illumination.

+ +

The hounds were streaming in by then, a quarter of the town, and not the +best quarter, though not necessarily the worst either; decent craftsmen, +merchants, traders, jostled with the riff-raff always ready for any brawl, and +all of them beyond themselves either with drink or excitement or both together, +howling for blood. And blood there was, slippery on the tiles of the floor. On +the three steps to the parish altar lay sprawled some poor wretch flattened +beneath a surge of trampling, battering foes, all hacking away with fist and +boot, happily in such a tangle that comparatively few of their kicks and blows +got home. All Cadfael could see of the quarry was a thin arm and a fist hardly +bigger than a child’s, that reached out of the chaos to grip the edge of the +altar-cloth with life-and-death desperation.

+ +

Abbot Radulfus, all the long, lean, muscular length of him, with his gaunt, +authoritative lantern head blazing atop, sailed round the altar, smoky candle +in hand, slashed the skirts of his habit like a whip across the stooping +beast-faces of the foremost attackers, and with a long bony leg bestrode the +fallen creature that clawed at the fringes of the altar.

+ +

“Rabble, stand off! Blasphemers, quit this holy place, and be ashamed. Back, +before I blast your souls eternally!”

+ +

He had no need to raise his voice to a shout, he had only to unsheathe it +like a knife, and it sliced through the babble as through cheese. They recoiled +as though his nearness seared, but they did not go far, only out of range of +the burning. They hopped and hovered and clamoured, indignant, aggrieved, but +wary of tempting Heaven. They drew off from a miserable fragment of a man, flat +on his face up the altar steps, soiled and crumpled and bloodied, and no bigger +than a boy fifteen years old. In the brief, daunted silence before they +screamed their charge against him, every soul present could hear how his breath +heaved and laboured and clapped in his ribs, toiling for dear life, threatening +to break his meagre frame apart. Flaxen hair dabbled with dust and blood +spilled against the fringes of the altar-cloth he gripped so frantically. +Skinny arms and legs hugged the stone as if his life depended upon the contact. +If he could speak, or lift his head, he had too much sense left in him to +venture the attempt.

+ +

“How dare you so affront the house of God?” demanded the abbot, darkly +smouldering. He had not missed the steely flash of reflected light in the hand +of one squat fellow who was sliding roundabout to get at his victim privily. “Put +up that knife or court your soul’s damnation!”

+ +

The hunters recovered breath and rage together. A dozen at least gave +tongue, crying their own justification and the hunted man’s offences, so +variously that barely a word conveyed any meaning. Radulfus brandished a +daunting arm, and their clamour subsided into muttering. Cadfael, observing +that the armed man had done no more than slide his weapon out of sight, took +his stand firmly between, and advanced his candles with a flourish in the +direction of a fine bushy beard.

+ +

“Speak one, if you have anything of worth to say,” ordered the abbot. “The +rest be silent. You, young man, you would seem to put yourself forward…”

+ +

The young man who had taken a pace ahead of his supporters, and whose prior +right they seemed to acknowledge, stood forth flushed and important, an +unexpected figure enough to be out man-hunting at midnight. He was tall and +well-made and assured of manner, a little too well aware of a handsome face, +and he was very elegant in festival finery, even if his best cotte was now +somewhat crumpled and disordered from the turmoil of pursuit, and his +countenance red and slack from the effects of a good deal of wine drunk. Without +that induced courage, he would not have faced the lord abbot with quite so much +impudence.

+ +

“My lord, I will speak for all, I have the right. We mean no disrespect to +the abbey or your lordship, but we want that man for murder and robbery done +tonight. I accuse him! All here will bear me out. He has struck down my father +and plundered his strong-box, and we are come to take him. So if your lordship +will allow, we’ll rid you of him.”

+ +

So they would, never a doubt of it. Radulfus kept his place, the brothers +crowding close to complete the barrier.

+ +

“I had thought to hear you make some amend,” said the abbot sharply, “for +this intrusion. Whatever this fellow may or may not have done, it is not he who +has shed blood and drawn steel here within the church on the very steps of the +altar. Violence he may have done elsewhere, but here none, he does but suffer +it. The crime of sacrilege is yours, all of you here breaking our peace. You +had best be considering on the health of your own souls. And if you have a lawful +complaint against this person, where is the law? I see no sergeant here among +you. I see no provost, who could at least make a case for the town. I see a +rabble, as far at fault in law as robber and murderer can be. Now get hence, +and pray that your offence may be pardoned. Whatever charges you have to make, +take them to the law.”

+ +

Some among them were drawing back stealthily by then, sobering and thinking +better of their invasion, and only too anxious to sneak away to their homes and +beds. But the vagabonds, always ready for mischief, stood their ground with +sullen, sly faces, and had no intention of going far, and the more respectable, +if they abated their noisy ardour, kept their bitter indignation. Cadfael knew +most of them. Perhaps Radulfus himself, though no Shrewsbury man by birth, was +better-read in them than they supposed. He kept his place, and bent his steady, +menacing brow against them, forbidding action.

+ +

“My lord abbot,” ventured the fine young man, “if you will let us take him +hence we will deliver him up to the law.”

+ +

To the nearest tree, thought Cadfael. And there were trees in plenty between +here and the river. He snipped at the wicks of his candles and let them flare +afresh. The beard was still hovering in the shadows.

+ +

“That I cannot do,” said the abbot crisply. “If the law itself were here, +there is no power can now take away this man from the sanctuary he has sought. +You should know the right of it as well as I, and the peril, body and soul, to +any who dare to breach that sanctuary. Go, take the pollution of your violence +out of this holy place. We have duties here which your presence in hatred +defiles. Go! Out!”

+ +

“But my lord,” bleated the angry young man, tossing his curled head but +keeping his distance, “you have not heard us as to the crime…”

+ +

“I will hear you,” said Radulfus with a snap, “by daylight, when you come +with sheriff or sergeant to discuss this matter calmly, and in proper form. But +I warn you, this man has claimed sanctuary, and the rights of sanctuary are +his, according to custom, and neither you nor any other shall force him away +out of these walls until the time of his respite is over.”

+ +

“And I warn you, my lord,” flared the youth, blazing red, “that should he +venture a step outside, we shall be waiting for him, and what falls out of your +lordship’s lordship will be no concern of yours, or the church’s.” Yes, +unquestionably he was moderately drunk, or he would never have gone so far, an +ordinary young burgess of the town, if a wealthy one. Even with an evening’s +wine in him, he blenched at his own daring, and shuffled back a pace or two.

+ +

“Or God’s?” said the abbot coldly. “Go hence in peace, before his bolt +strike you.”

+ +

They went, shadows edging backwards into shadow, through the open west door +and out into the night, but always with their faces turned towards the +miserable bundle prostrate clutching the altar-cloth. Mob madness is not so +easily subdued, and even if their grievance proved less than justified, it was +real enough to them. Murder and robbery were mortal crimes. No, they would not +all go away. They would set a watch on the parish door and the gatehouse, with +a rope ready.

+ +

“Brother Prior,” said Radulfus, running an eye over his shaken flock, “and +Brother Precentor, will you again begin Lauds? Let the office proceed, and the +brothers return to their beds according to the order. The affairs of men +require our attention, but the affairs of God may not be subordinated.” He +looked down at the motionless fugitive, too tensely still not to be aware of +everything that passed above him, and again looked up to catch Brother +Cadfael’s concerned and thoughtful eye. “We two, I think, are enough to take +what confession this guest of ours wills to make, and tend his needs. They are +gone,” said the abbot dispassionately to the prone figure at his feet. “You may +get up.”

+ +

The thin body stirred uneasily, keeping one hand firmly on the fringe of the +altar-cloth. He moved as if every flinching movement hurt, as well it might, +but it seemed that he had at least escaped broken bones, for he used his free +arm to help him up to his knees on the steps, and raised to the light a gaunt, +bruised face smeared with blood and sweat and the slime of a running nose. +Before their eyes he seemed to dwindle both in years and size. They might have +been gazing at some unlucky urchin of the Foregate who had been set upon by a +dozen or more of his capricious fellows for some trivial offence, and left +howling in a ditch, but for the desperation of fear that emanated from him, and +the memory of the pack that had been beaten off from his heels just in time.

+ +

A poor little wretch enough to be credited with murder and robbery. On his +feet he might perhaps be about as tall as Cadfael, who was below the middle +height, but width-ways Cadfael would have made three of him. His cotte and hose +were ragged and threadbare, and had several new rents in them now from clawing +hands and trampling feet, besides the dust and stains of long use, but +originally they had been brightly-coloured in crude red and blue. He had a +decent width of shoulder, better feeding might have made a well-proportioned +man of him, but as he moved stiffly to look up at them he seemed all gangling +limbs, large of elbow and knee, and very low in flesh to cover them. Seventeen +or eighteen years old, Cadfael guessed. The eyes raised to them in such +desolate entreaty were hollow and evasive, and one of them half-closed and +swelling, but in the light of the candles they flared darkly and brilliantly +blue as periwinkle flowers.

+ +

“Son,” said Radulfus, with chill detachment, for murderers come in all +shapes, ages and kinds, “you heard what is charged against you by those who +surely sought your life. Here you have committed body and soul to the care of +the church, and I and all here are bound to keep and succour you. On that you +may rely. As at this moment, I offer you only one channel to grace, and ask of +you but one question. Whatever the answer, here you are safe as long as the +right of sanctuary lasts. I promise it.”

+ +

The wretch crouched on his knees, watching the abbot’s face as though he +numbered him among his enemies, and said no word.

+ +

“How do you answer to this charge?” asked Radulfus. “Have you this day +murdered and robbed?”

+ +

Distorted lips parted painfully to loose a light, high, wary voice like a +frightened child’s. “No, Father Abbot, I swear it!”

+ +

“Get up,” said the abbot, neither trusting nor judging. “Stand close, and +lay your hand upon this casket on the altar. Do you know what it contains? Here +within are the bones of the blessed Saint Elerius, the friend and director of +Saint Winifred. On these holy relics, consider and answer me once again, as God +hears you: are you guilty of that which they charge you?”

+ +

With all the obstinate, despairing fervour so slight a body could contain, +and without hesitation, the light voice shrilled: “As God sees me, I am not! I +have done no wrong.”

+ +

Radulfus considered in weighty silence an unnerving while. Just so would a +man answer who had nothing to hide and nothing to fear from being heard in Heaven. +But no less, so would a godless vagabond answer for his hide’s sake, having no +faith in Heaven, and no fear of anything beyond the terrors of this world. Hard +to decide between the two. The abbot suspended judgement.

+ +

“Well, you have given a solemn word, and whether it be true or no, you have +the protection of this house, according to law, and time to think on your soul, +if there is need.” He looked at Cadfael, and eye to eye they considered the +needs that came before all. “He had best keep to the church itself, I think, +until we have spoken with the officers of law, and agreed on terms.”

+ +

“So I think, also,” said Cadfael.

+ +

“Should he be left alone?” They were both thinking of the pack recently +expelled from this place, still hungry and ripe for mischief, and surely not +gone far.

+ +

The brothers had withdrawn, led back to the dortoir by Prior Robert, very +erect and deeply displeased. The choir had grown silent and dark. Whether the +brethren, particularly the younger and more restless, would sleep, was another +matter. The smell of the dangerous outer world was in their nostrils, and the +tremor of excitement quivering like an itch along their skins.

+ +

“I shall have work with him a while,” said Cadfael, eyeing the smears of +blood that marked brow and cheek, and the painful list with which the man +stood. A young, willowy body, accustomed to going lightly and lissomely. “If +you permit, Father, I will stay here with him, and take his care upon me. Should +there be need, I can call.”

+ +

“Very well, do so, brother. You may take whatever is necessary for his provision.” +The weather was mild enough, but the hours of the night would be cold, in this +sanctified but stony place. “Do you need a helper to fetch and carry for you? +Our guest should not be left unfellowed.”

+ +

“If I may borrow Brother Oswin, he knows where to find all the things I may +need,” said Cadfael.

+ +

“I will send him to you. And should this man wish to tell his own side of +this unhappy story, mark it well. Tomorrow, no doubt, we shall have his +accusers here in proper form, with one of the sheriff’s officers, and both +parties will have to render account.”

+ +

Cadfael understood the force of that. A small discrepancy in the accused +youth’s story between midnight and morning could be revealing indeed. But by +morning the voluble accusers might also have cooled their heads, and come with +a slightly modified tale, for Cadfael, who knew most of the inhabitants of the +town, had by this time recalled the reason for their being up so late in their +best clothes, and well gone in drink. The young cockerel in the festival finery +should by rights have been bedding a bride rather than pursuing a wretched wisp +of manhood over the bridge with hunting cries of murder and robbery. Nothing +less than the marriage of the heir could have unloosed the purse-strings of the +Aurifaber household enough to provide such a supply of wine.

+ +

“I leave the watch to you,” said Radulfus, and departed to hale out Brother +Oswin from his cell, and send him down to join the vigil, He came so blithely +that it was plain he had been hoping for just such a recall. Who but Brother +Cadfael’s apprentice should be admitted to his nocturnal ministrations? Oswin +came all wide eyes and eager curiosity, as excited as a truant schoolboy at +being footloose at midnight, and attendant on the fringes of a sensational +villainy. He hung over the shivering stranger, between fascinated horror at +viewing a murderer close, and surprised pity at seeing so miserable a human +being, where a brutal monster should have been.

+ +

Cadfael gave him no time to marvel. “I want water, clean linen, the ointment +of centaury and cleavers, and a good measure of wine. Hop to it, sharp! Better +light the lamp in the workshop, we may need more things yet.”

+ +

Brother Oswin plucked out a candle from its socket, and departed in such a +gust of dutiful enthusiasm that it was a marvel his light was not blown out in +the doorway. But the night was still, and the flame recovered, streaming +smokily across the great court towards the gardens.

+ +

“Light the brazier!” called Cadfael after him, hearing his wretched charge’s +teeth begin to chatter. A close brush with death is apt to leave a man +collapsing like a pricked bladder, and this one had little flesh or strength +about him to withstand the shock. Cadfael got an arm about him before he folded +like an empty coat, and slid to the stones.

+ +

“Here, come… Let’s get you into a stall.” The weight was slight as a +child’s, he hoisted it bodily, and made to withdraw round the parish altar to +the somewhat less draughty confines of the choir, but the skinny fist that had +all this time held fast to the altar-cloth would not let go. The thin body +jerked in his arms.

+ +

“If I loose, they’ll kill me…”

+ +

“Not while I have hands or voice,” said Cadfael. “Our abbot has held his +hand over you, they’ll make no further move tonight. Leave go of the cloth and +come within. There are relics enough there, trust me, holier even than this.”

+ +

The grubby fingers, with black and bitten nails, released the cloth reluctantly, +the flaxen head drooped resignedly on Cadfael’s shoulder. Cadfael bore him +round into the choir and laid him in the nearest and most commodious stall, +which was that of Prior Robert. The usurpation was not unpleasing. The young +man was shivering violently from head to toe, but relaxed into the stall with a +huge sigh, and was still.

+ +

“They’ve hunted you into the ground,” Cadfael allowed, settling him into +shelter, “but at least into the right earth. Abbot Radulfus won’t give you up, +never think it. You can draw breath, you have a home here for some days to +come. Take heart! Nor are that pack out there so bad as you suppose, once the +drink’s out of them they’ll cool. I know them.”

+ +

“They meant to kill me,” said the youth, trembling.

+ +

No denying that. So they would have done, had they got their hands on him +out of this enclave. And there was a note of simple bewilderment in the high +voice, of terror utterly at a loss, that caught Cadfael’s leaning ear. The lad +was far gone in weakness, and relief from fear, and truly it sounded as if he +did not know why he had ever been threatened. So the fox must feel, acting +innocently after his kind, and hearing the hounds give tongue.

+ +

Brother Oswin came, burdened with a scrip full of wine-flask and +unguent-jar, a roll of clean linen under one arm, and a bowl of water in both +hands. His lighted candle he must have stuck to the bench in the porch, where a +tiny, flickering light played. He arrived abrupt, urgent and glowing, the +light-brown curls round his tonsure erected like a thorn-hedge. He laid down +his bowl, laid out his linen, and leaned eagerly to support the patient as +Cadfael drew him to the light.

+ +

“Be thankful for small mercies, I see no sign of broken bones in you. You’ve +been trampled and hacked, and I make no doubt you’re a lump of bruises, but +that we can deal with. Lean here your head—so! That’s a nasty welt across your +temple and cheek. A cudgel did that. Hold still, now!”

+ +

The fair head leaned submissively into his hands. The weal grazed the crest +of the left cheekbone, and broke the skin along the left side of his head, +oozing blood into the pale hair. As Cadfael bathed it, stroking back the +tangled locks, the skin quivered under the cold water, and the muck of dust and +drying blood drained away. This was not the newest of his injuries. The +smoothing of the linen over brow, cheek and chin uncovered a thin, pure, +youthful face.

+ +

“What’s your name, child?” said Cadfael.

+ +

“Liliwin,” said the young man, still eyeing him warily.

+ +

“Saxon. So are your eyes, and your hair. Where born? Not here along the +borders.”

+ +

“How should I know?” said the youth, listless. “In a ditch, and left there. +The first I know is being taught to tumble, as soon as I walked.”

+ +

He was past fending for himself; perhaps he was even past lying. As well to +get out of him whatever he was willing to tell, now, while he was forced to +surrender himself to the hands of others, with his own helplessness like a +weight of black despair on him.

+ +

“Is that how you’ve lived? Travelling the road, cutting capers at fairs, +doing a little juggling and singing for your supper? It’s a hard life, with +more kicks than kindnesses, I dare say. And from a child?” He could guess at +the manner of training that went to school a childish body to the sort of +contortions a fairground crowd would gape at. There were ways of hurting, by +way of punishment, without spoiling the agility of growing limbs. “And solitary +now? They’re gone, are they, that picked you out of your ditch and bent you to +their uses?”

+ +

“I ran from them as soon as I was half-grown,” said the soft, weary voice. “Three +mummers padding the road, a lad come by for nothing was a gift to them, they +had their worth out of me. All I owed them was kicks and blows. I work for +myself now.”

+ +

“At the same craft?”

+ +

“It’s all I know. But that I know well,” said Liliwin, suddenly raising his +head proudly, and not wincing from the sting of the lotion bathing his grazed +cheek.

+ +

“And that’s what brought you to Walter Aurifaber’s house last night,” said +Cadfael mildly, stripping back a torn sleeve from a thin, sinewy forearm marked +by a long slash from a knife. “To play at his son’s wedding-feast.”

+ +

One dark-blue eye peered up at him sidelong. “You know them?”

+ +

“There are few people in the town that I don’t know. I tend many folk within +the walls, the old Aurifaber dame among them. Yes, I know that household. But +it had slipped my mind that the goldsmith was marrying his son yesterday.” +Knowing them as well as he did, he was sure that for all their wish to make an +impressive show, they would not pay out money enough to attract the better sort +of musicians, such as the nobility welcomed as guests. But a poor vagrant +jongleur trying his unpromising luck in the town, that they might consider. All +the more if his performance outdid his appearance, and genuine music could be +had dead cheap. “So you heard of the celebration, and got yourself hired to +entertain the guests. Then what befell, to bring the jollity to such a grim +ending? Reach me here a pad of cloth, Oswin, and hold the candle nearer.”

+ +

“They promised me three pence for the evening,” said Liliwin, trembling now +as much with indignation as fear and cold, “and they cheated me. It was none of +my fault! I played and sang my best, did all my tricks… The house was full of +people, they crowded me, and the young fellows, they were drunk and lungeous, +they hustled me! A juggler needs room! It was not my fault the pitcher was +broken. One of the youngsters jumped to catch the balls I was spinning, he +knocked me flying, and the pitcher went over from the table, and smashed. She +said it was her best… the old beldame… she screeched at me, and hit out with +her stick…”

+ +

“She did this?” questioned Cadfael gently, touching the swathed wound on the +jongleur’s temple.

+ +

“She did! Lashed out like a fury, and swore the thing was worth more than +I’d earned, and I must pay for it. And when I complained, she threw me a penny, +and told them to put me out!”

+ +

So she would, thought Cadfael ruefully, seeing her life-blood spilled if a +prized possession was broken, she who hoarded every groat that was not spent on +her perverse tenderness for her soul, which brought alms flowing to the abbey +altars, and rendered Prior Robert her cautious friend.

+ +

“And they did it?” It would not have been a gentle ejection, they would all +have been inflamed and boisterous by them. “How late was that? An hour before midnight?”

+ +

“More. None of them had left, then. They tossed me out of door, and wouldn’t +let me in again.” He had long experience of his own helplessness in similar +circumstances, his voice sagged despondently. “I couldn’t even pick up my juggling +balls, I’ve lost them all.”

+ +

“And you were left chill in the night, thrown out of the burgage. Then how +came this hunt after you?” Cadfael smoothed a turn of his linen roll round the +thin arm that jerked in his hands with frustrated rage. “Hold still, child, +that’s right! I want this slit well closed, it will knit clean if you take +ease. What did you do?”

+ +

“Crept away,” said Liliwin bitterly. “What else could I do? The watch let me +out of the wicket in the town gate, and I crossed the bridge and slipped into +the bushes this side, meaning to make off from this town in the morning, and +make for Lichfield. There’s a decent grove above the path down to the river, +the other side the highroad from the abbey here, I went in there and found me a +good place in the grass to sleep the night out.” But with his grievance boiling +and festering in him, and his helplessness over and above, if what he told was +truth. And long acquaintance with injustice and despite does not reconcile the +heart.

+ +

“Then how comes it the whole pack of them should be hunting you an hour or +so later, and crying murder and theft on you?”

+ +

“As God sees me,” blurted the youth, quaking, “I know no more than you! I +was near to sleeping when I heard them come howling across the bridge. I’d no +call to suppose it was ought to do with me, not until they were streaming down +into the Foregate, but it was a noise to make any man afraid, whether he’d +anything on his conscience or no. And then I could hear them yelling murder and +vengeance, and crying it was the mumper who did it, and baying for my blood. They +spread out and began to beat the bushes, and I ran for my life, being sure +they’d find me. And all the pack of them came roaring after. They were all but +plucking at my hair when I stumbled in here at the door. But God strike me +blind if I know what I’m held to have done—and dead if I’m lying to you now!”

+ +

Cadfael completed his bandage, and drew the tattered sleeve down over it. “According +to young Daniel, it seems his father’s been struck down and his strong-box +emptied. A poor way of rounding off a wedding night! Do you tell me all this +can have happened after you were put out without your pay? On the face of it, +that might turn their minds to you and your grievance, if they were casting +about for a likely felon.”

+ +

“I swear to you,” insisted the young man vehemently, “the goldsmith was hale +and well the last time I set eyes on him. There was no quarrelling, no violence +but what they used on me, they were laughing and drinking and singing still. +What’s happened since I know no more than you. I left the place—what use was +there in staying? Brother, for God’s sake believe me! I’ve touched neither the +man nor his money.”

+ +

“Then so it will be found,” said Cadfael sturdily. “Here you’re safe enough +in the meantime, and you must needs put your trust in justice and Abbot +Radulfus, and tell your tale as you’ve told it to me when they question you. We +have time, and given time, truth will out. You heard Father Abbot—stay here +within the church tonight, but if they come to a decent agreement tomorrow you +may have the run of the household.” Liliwin was very cold to the touch, with +fear and shock, and still trembling. “Oswin,” said Cadfael briskly, “go and +fetch me a couple of brychans from the store, and then warm me up another good +measure of wine on the brazier, and spice it well. Let’s get some warmth into +him.”

+ +

Oswin, who had held his tongue admirably while his eyes devoured the +stranger, departed in a flurry of zeal to do his errands. Liliwin watched him +go, and then turned to watch Cadfael no less warily. Small wonder if he felt +little trust in anyone just now.

+ +

“You won’t leave me? They’ll be peering in at the door again before the night’s +out.”

+ +

“I won’t leave you. Be easy!”

+ +

Advice difficult to follow, he admitted wryly, in Liliwin’s situation. But +with enough mulled wine in him he might sleep. Oswin came again glowing with +haste and the flush of bending over the brazier, and brought two thick, rough +blankets, in which Liliwin thankfully wound himself. The spiced draught went +down gratefully. A little colour came back to the gaunt, bruised face.

+ +

“You go to your bed, lad,” said Cadfael, leading Oswin towards the night +stairs. “You can, now, he’ll do till morning. Then we shall see.”

+ +

Brother Oswin looked back in some wonder at the swaddled body almost +swallowed up in Prior Robert’s capacious stall, and asked in a whisper: “Do you +think he can really be a murderer, though?”

+ +

“Child,” said Cadfael, sighing, “until we get some sensible account of +what’s happened in Walter Aurifaber’s burgage tonight, I doubt if there’s been murder +done at all. With enough drink in them, the fists may well have started flying, +and a few noses been bloodied, and some fool may very well have started a +panic, with other fools ready enough to take up the cry. You go to your bed, +and wait and see.”

+ +

And so must I wait and see, he thought, watching Oswin obediently climb the +stair. It was all very well distrusting the alarms of the moment, but for all +that, not all those voluble accusers had been drunk. And something unforeseen +had certainly happened in the goldsmith’s house, to put a violent end to the +celebrations of young Daniel’s marriage. How if Walter Aurifaber had really +been struck dead? And his treasury robbed? By that woebegone scrap of humanity +huddled in his brychans, half-drunk with the wine they had poured into him, +half asleep but held alert by terror? Would he dare, even with a bitter +grievance? Could he have managed the affair, even if he had dared? One thing +was certain, if he had robbed he must have disposed of his gains in short order +in the dark, in a town surely none too well known to him. In those scanty +garments of his, that threadbare motley, there was barely room to conceal the +single penny the old dame had thrown at him, much less the contents of a +goldsmith’s coffer.

+ +

When he approached the stall, however quietly, the bruised eyelids rolled +wide from the dark blue eyes, and they fixed on him in instant dread.

+ +

“Never shrink, it’s I. No one else will trouble you this night. And my name, +if you need it, is Cadfael. And yours is Liliwin.” A name strangely right for a +vagabond player, very young and solitary and poor, and yet proud of his +proficiency in his craft, tumbler, contortionist, singer, juggler, dancer, +purveying merriment for others while he found little cause to be merry himself. +“How old are you, Liliwin?”

+ +

Half asleep and afraid to give way and sleep in earnest, he looked ever +younger, dwindling into a swaddled child, reassuringly flushed now as the chill +ebbed out of him. But he himself did not know the answer. He could only knit +his fair brows and hazard doubtfully: “I think I may be turned twenty. It could +be more. The mummers may have said I was less than I was—children draw more +alms.”

+ +

So they would, and the boy was lightly built, spare and small. He might be +as much as two and twenty, perhaps, surely no more.

+ +

“Well, Liliwin, if you can sleep do so, it will be aid and comfort, and you +have need of it. You need not watch, I shall be doing that.”

+ +

Cadfael sat down in the abbot’s stall, and trimmed the attendant candles, so +that he might have a fair view of his charge. The quiet came in, on the heels +of their silence, very consolingly. The night without might well have its +disquiets, but here the vault of the choir was like linked hands sheltering +their threatened and precarious peace. It was strange to Cadfael to see, after +prolonged calm, two great tears welling from beneath Liliwin’s closed eyelids, +and rolling slowly over the jut of his gaunt cheek-bone, to fall into the +brychan.

+ +

“What is it? What troubles you?” For himself he had shivered, argued, +burned, but not wept.

+ +

“My rebec—I had it with me in the bushes, in a linen bag for my shoulder. +When they flushed me out—I don’t know how, a branch caught in the string, and +plucked it away. And I dared not stop to grope for it in the dark… And now I +can’t go forth! I’ve lost it!”

+ +

“In the bushes, this side the bridge—across the highway from here?” It was a +grief Cadfael could comprehend. “You cannot go forth lad, no, not yet, true +enough. But I can. I’ll look for it. Those who hunted you would not go +aside once they had you in view. Your rebec may be lying safe enough among the +bushes. Go to sleep and leave grieving,” said Cadfael. “It’s too early to +despair. For despair,” he said vigorously, “it is always too early. Remember that, +and keep up your heart.”

+ +

One startled blue eye opened at him, he caught the gleam of the candles in +it before it closed again. There was silence. Cadfael lay back in the abbot’s +stall, and resigned himself to a long watch. Before Prime he must rouse himself +to remove the interloper to a less privileged place, or Prior Robert would be +rigid with offence. Until then, let God and his saints take charge, there was +nothing more mere man could do.

+ +

As soon as the first light of dawn began to pluck colours out of the dark, +on this clear May morning, Griffin, the locksmith’s boy who slept in the shop +as a watchman, got up from his pallet and went to draw water from the well in +the rear yard. Griffin was always the first up, from either household of the +two that shared the yard, and had usually kindled the fire and made all ready +for the day’s work before his master’s journeyman came in from his home two +streets away. On this day in particular Griffin took it for granted that all +those who had kept it up late at the wedding would be in no condition to rise +early about their work. Griffin himself had not been invited to the feast, +though Mistress Susanna had sent Rannilt across to bring him a platter of meats +and bread, a morsel of cake and a draught of small ale, and he had eaten his +fill, and slept innocently through whatever uproar had followed at midnight.

+ +

Griffin was thirteen years old, offspring of a maidservant and a passing +tinker. He was well-grown, comely, of contented nature and good with his hands, +but he was a simpleton. Baldwin Peche the locksmith preened himself on his +goodness in giving house-room to such an innocent, but the truth was that Griffin, +for all his dimness of wit, had a gift for picking up practical skills, and far +more than earned his keep.

+ +

The great wooden bucket, its old boards worn and fretted within and without +from long use, came up out of the depths sparkling in the first slanting ray of +the rising sun. Griffin filled his two pails, and was slinging the bucket back +over the shaft when the gleam caught a flash of silver between two of the +boards, lodged edgeways in the crevice. He balanced the bucket on the stone rim +of the well, and leaned and fished out the shining thing, tugging it free +between finger and thumb, and shaking off a frayed shred of blue cloth that +came away with it. It lay in his palm shining, a round disc of silver prettily +engraved with a head, and some strange signs he did not know for letters. On +the reverse side there was a round border and a short cross within it, and more +of the mysterious signs. Griffin was charmed. He took his prize back with him +to the workshop, and when Baldwin Peche finally arose from his bed and came +forth blear-eyed and cross-grained, the boy presented him proudly with what he +had found. Whatever belonged here belonged to his master.

+ +

The locksmith clapped eyes on it and kindled like a lighted lamp, head and +eyes clearing marvellously. He turned it in his fingers, examining both sides +closely, and looked up with a curious, private grin and a cautious question:

+ +

“Where did you find this, boy? Have you shown it to anyone else?”

+ +

“No, master, I brought it straight in for you. It was in the bucket of the +well,” said Griffin, and told him how it had lodged between the boards.

+ +

“Good, good! No need to let others know I have such. Stuck fast in the +boards, was it?” mused Baldwin, brooding gleefully over his treasure. “You’re a +good lad! A good lad! You did right to bring it straight to me, I set a great +value on this! A great value! He was grinning to himself with immense +satisfaction, and Griffin reflected his content proudly. I’ll give you some +sweetmeats to your dinner I got from last night’s feast. You shall see I can be +grateful to a dutiful boy.”

+
+
+

Chapter Two

+ +

« ^ »

+ +

Saturday, from Prime to noon

+ +

Brother Cadfael +had Liliwin awake and made as presentable as possible before the brothers came +down to Prime. He had risked helping him out at first light to the necessary +offices, where he might at least wash his battered face and relieve himself, +and return to stand up before the assembled convent at Prime with some sad +dignity. Not to speak of the urgent need to have Prior Robert’s stall vacant +and ready for him, for Robert’s rigid disapproval of the intrusion and the +intruder was already sufficiently clear, and there was no need to aggravate his +hostility. The accused had enough enemies already.

+ +

And in they came at the gatehouse, just as the +brothers emerged from Prime, a solid phalanx of citizens intent on lodging +their accusations this time in due and irreproachable form. Sheriff Prestcote +had deputed the enquiry and negotiations to his own sergeant, having more +important items of the king’s business on his hands than a passing assault and +robbery in a town dwelling. He was newly back from his Easter attendance at +King Stephen’s court and the delivery of the shire accounts and revenues, and +his early summer survey of the county’s royal defences was about to begin. +Already Hugh Beringar, his deputy, was in the north of the shire about the same +necessary business, though Cadfael, who relied on Hugh’s good sense in all +matters of poor souls fetched up hard against the law, hoped fervently that he +would soon be back in Shrewsbury to lend a shrewd eye and willing ear to both +sides in the dispute. The accusers had always the advantage without a healthy +sceptic in attendance.

+ +

Meantime, here was the sergeant, large, +experienced and sharp enough, but disposed to the accusers rather than the +accused, and with a formidable array of townsmen behind him, led by the +provost, Geoffrey Corviser. A decent, stout, patient man, and in no hurry to +condemn without conscientious probing, but already primed with the complaints +of several equally solid citizens, in addition to the aggrieved family. A +wedding party provides at once large numbers of witnesses, and a powerful +argument for doubting the half of their evidence.

+ +

Behind the authorities of shire and town came +young Daniel Aurifaber, slightly the worse for wear after his hectic and +unorthodox wedding night, and in his working clothes this time, but still +belligerent. Surely, however, not so disturbed as a young man should be at his +father’s untimely slaying? Even slightly sheepish, and all the surlier because +of it.

+ +

Cadfael withdrew to the rear of the brothers, +between the citizen army and the church, and prepared to block the doorway if +any of the witnesses should again lose his head and dare the abbot’s thunder. +It did not seem likely, with the sergeant there in control, and well aware of +the necessity of dealing civilly and amicably with a mitred abbot. But in any +dozen men there may well be one incorrigible idiot capable of any folly. +Cadfael cast a glance over his shoulder, and glimpsed a pallid, scared face, +but a body still, silent and intent, whether trusting in his ecclesiastical +shelter, or simply resigned, there was no knowing.

+ +

“Keep within, out of sight, lad,” said Cadfael +over his shoulder, “unless you’re called for. Leave all to the lord abbot.”

+ +

Radulfus greeted the sergeant composedly, and +after him the provost.

+ +

“I expected your visit, after the night’s alarm. I +am acquainted with the charges then made against a man who has appealed to +sanctuary within our church, and been received according to our duty. But the +charges have no force until made in due form, through the sheriff’s authority. +You are very welcome, sergeant, I look to you to inform me truly how this +matter stands.”

+ +

He had no intention, Cadfael thought, watching, of +inviting them withindoors into chapterhouse or hall. The morning was fine and +sunny, and the matter might be agreed more briskly here, standing. And the +sergeant had already recognised that he had no power to take the fugitive out +of the hands of the church, and was intent only on agreeing terms, and hunting +his proofs elsewhere.

+ +

“There is a charge lodged with me,” he said +practically, “that the jongleur Liliwin, who was employed last night to play at +a wedding in the house of Master Walter Aurifaber, struck down the said Walter +in his workshop, where he was then laying away certain valuable wedding gifts +in his strong-box, and robbed the strong-box of a treasure in coins and +goldsmith’s work to a great value. This is sworn to by the goldsmith’s son, here +present, and by ten of the guests who were at the feast.”

+ +

Daniel braced his feet, stiffened his neck, and +nodded emphatic confirmation. Several of the neighbours at his back murmured +and nodded with him.

+ +

“And you have satisfied yourself,” said Radulfus briskly, +“that the charges are justified? At least, whoever did them, that these deeds +were done?”

+ +

“I have viewed the workshop and the strong-box. +The box is emptied of all but heavy items of silverware that would be ill to +carry undetected. I have taken sworn witness that it held a great sum in silver +pence and small, fine works of jewellery. All are gone. And as to the act of +violence against Master Aurifaber, I have seen the marks of his blood close to +the coffer, where he was found, and I have seen how he lies still out of his +senses.”

+ +

“But not dead?” said Radulfus sharply. “It +was murder was cried here at midnight.”

+ +

“Dead?” The sergeant, an honest man, gaped at the +suggestion. “Not he! He’s knocked clean out of his wits, but it was not so +desperate a blow as all that. If he hadn’t had a fair wash of drink in him he +might have been fit to speak up for himself by now, but he’s still addled. It +was a fair dunt someone gave him, but with a good hard head… No, he’s well +alive, and will live his proper span if I’m a judge.”

+ +

The witnesses, solid and sullen at his back, +shifted their feet and looked elsewhere, but covertly came back to eyeing the +abbot and the church door, and if they were discomfited at having their largest +claims refuted, nonetheless held fast to their mortal grievance, and wanted a +neck stretched for it.

+ +

“It seems, then,” said the abbot composedly, “that +the man we have in sanctuary is accused of wounding and robbing, but not of +murder.”

+ +

“So it stands. The evidence is that he was docked +of his full fee because he broke a pitcher in his juggling, and complained +bitterly when he was put out. And some time after that, this assault upon +Master Aurifaber was made, while most of those invited were still there in the +house, and vouched for.”

+ +

“I well understand,” said the abbot, “that on such +a charge you must enquire, and may justice be done. But I think you also know +well the sacredness of sanctuary. It is not shelter against sin, it is the +provision of a time of calm, when the guilty may examine his soul, and the +innocent confide in his salvation. But it may not be violated. It has a period, +but until that time is spent it is holy. For forty days the man you seek on +this charge is ours—no, he belongs to God!—and he may not be haled forth, nor +persuaded forth, nor any way removed against his will from these premises. He +is ours to feed, to care for and to shelter, for those forty days.”

+ +

“That I grant,” said the sergeant. “But there are +conditions. He came of his own will within, he may enjoy only the allowance of +food those within here enjoy.” Less than he did, by his lusty bulk, but surely +more than Liliwin had ever enjoyed as his regular provision. “And when the +respite is over, he may not again be supplied with food, but must come forth +and submit himself to trial.”

+ +

He was as iron-sure of his case here as was +Radulfus in the days of grace, he voiced his mandate coldly. There would be no +extension of the time allowed, after that they would make sure he starved until +he came forth. It was fair. Forty days is consideration enough.

+ +

“Then during that time,” said the abbot, “you +agree that the man may rest here and study on his soul. My concern for justice +is no less than yours, you know I will keep to terms, and neither make nor +allow others to make any offer to help the man away out of hold and out of your +reach. But it would be seemly to agree that he need not confine himself to the +church, but have the freedom of the whole enclosure here, so that he may make +use of the lavatorium and necessarium, take some exercise in the open air, and +keep himself decent among us.”

+ +

To that the sergeant agreed without demur. “Inside +your pale, my lord, he may make free. But if he step one pace outside, my men +will be ready and waiting for him.”

+ +

“That is understood. Now, if you so wish, you may +speak with the accused youth, in my presence, but without these witnesses. +Those who charge him have told their story, it is fair that he should also tell +his just as freely. After that, the matter must wait for trial and judgement hereafter.”

+ +

Daniel opened his mouth as if to make furious +protest, caught the abbot’s cold eye, and thought better of it. The henchmen at +his back shuffled and muttered, but did not venture to be clearly heard. Only +the provost spoke up, in the interests of the town in general.

+ +

“My lord, I was not a guest at yesterday’s +marriage, I have no direct knowledge of what befell. I stand here for the fair +mind of Shrewsbury, and with your leave I would wish to hear what the young man +may say for himself.”

+ +

The abbot agreed to that willingly. “Come, then, +into the church. And you, good people, may disperse in peace.” So they did, +still with some reluctance at not getting their hands immediately on their +prey. Only Daniel, instead of withdrawing, stepped forward hastily to arrest +the abbot’s attention, his manner now anxious and ingratiating, his grievance +put away in favour of a different errand.

+ +

“Father Abbot, if you please! It’s true we all ran +wild last night, finding my poor father laid flat as he was, and bleeding. Truly +we did believe him murdered, and cried it too soon, but even now there’s no +knowing how badly he’s hurt. And my old grandmother, when she heard it, fell in +a seizure, as she has once before, and though she’s better of it now, she’s +none too well. And from the last fit she had, she puts more faith in Brother +Cadfael’s remedies than in all the physicians. And she bid me ask if he may +come back with me and medicine her, for he knows what’s needed when this +breathlessness takes her, and the pains in her breast.”

+ +

The abbot looked round for Cadfael, who had come +forth from the shadow of the cloister at hearing this plea. There was no +denying he felt a distinct quiver of anticipation. After the night he had spent +beside Liliwin, he could not help being consumed with curiosity as to what had +really happened at Daniel Aurifaber’s wedding supper.

+ +

“You may go with him, Brother Cadfael, and do what +you can for the woman. Take whatever time you need.”

+ +

“I will, Father,” said Cadfael heartily, and went +off briskly into the garden, to fetch what he thought might be required from +his workshop.

+ +

The goldsmith’s burgage was situated on the street +leading to the gateway of the castle, where the neck of land narrowed, so that +the rear plots of the houses on either side the street ran down to the town +wall, while the great rondel of Shrewsbury lay snug to the south-west in the +loop of the

+ +

Severn. It was one of the largest plots in the +town, as its owner was thought to be one of the wealthiest men; a right-angled +house with a wing on the street, and the hall and main dwelling running +lengthwise behind. Aurifaber, ever on the lookout for another means of making +money, had divided off the wing and let it as a shop and dwelling to the +locksmith Baldwin Peche, a middle-aged widower without children, who found it +convenient and adequate to his needs. A narrow passage led through between the +two shops to the open yard behind, with its well, and the separate kitchens, +byres and privies. Rumour said of Walter Aurifaber that he even had his cesspit +stone-lined, which many considered to be arrogating to himself the privileges +of minor nobility. Beyond the yard the ground fell away gradually in a long +vegetable-garden and fowl-run to the town wall, and the family holding extended +even beyond, through an arched doorway to an open stretch of smooth grass going +down to the riverside.

+ +

Cadfael had paid several visits to the house at +the old woman’s insistence, for she was now turned eighty years old, and held +that her gifts to the abbey entitled her to medical care in this world, as well +as purchasing sanctity for the next. At eighty there is always something ailing +the body, and Dame Juliana was given to ulcers of the leg if she suffered any +slight wound or scratch, and stirred very little from her own chamber, which +was one of the two over the hall. If she had presided at Daniel’s wedding +supper, as clearly she had, it must have been with her walking-stick ready to +hand—unluckily for Liliwin! She was known to be willing to lash out with it +readily if anything displeased her.

+ +

The only person on whom she doted, people said, +was this young sprig of a grandson of hers, and even he had never yet found a +way to get her to loose her purse-strings. Her son Walter was made in her own +image, as parsimonious as the dame, but either surer of his own virtue as +admitting him by right to salvation, or else not yet so old as to be worrying +about the after-life, for the abbey altars owed no great benefits to him. There +would have been an impressive show for the heir’s wedding, but the pence that +paid for it would be screwed out of the housekeeping for the next few months. +It was a sour joke among those who did not like the goldsmith that his wife had +died of starvation as soon as she had borne him a son, spending on her keep +being no longer necessary.

+ +

Cadfael followed a glum and taciturn Daniel +through the passage between the shops. The hall door stood wide open on the +yard, at this hour in long shadow, but with a pale blue sky radiant overhead. +Within, timber-scented gloom closed on them. There was a chamber door on the +right, the daughter’s room, and beyond that the household stores over which she +presided. Beyond that doorway the stairs went up to the upper floor. Cadfael +climbed the broad, unguarded wooden steps, needing no guidance here. Juliana’s +chamber was the first door off the narrow gallery that ran along the side wall. +Daniel, without a word, had slouched back out of the hall below, and made for +the shop. For a few days, at least, he was the goldsmith. A good workman, too, +they said, when he chose, or when his elders could hold him to it.

+ +

A woman came out of the room as Cadfael approached +it. Tall, like her young brother, of the same rich brown colouring, past thirty +years old and mistress of this household for the last fifteen of those years, +Walter’s daughter Susanna had a cool dignity about her that went very ill with +violence and crime. She had stepped into the shoes of her mother, whom she was +said to resemble, as soon as Dame Juliana began to ail. The keys were hers, the +stores were hers, the pillars and the roof of the house were held up by her, +calmly and competently. A good girl, people said. Except that her girlhood was +gone.

+ +

She smiled at Brother Cadfael, though even her +smile was distant and cool. She had a pale, clear oval face with wide-set grey eyes, +that went very strangely with her wealth of russet hair, braided and bound +austerely on her head. Her housewifely gown was neat, dark and plain. The keys +at her waist were her only jewellery.

+ +

They were old acquaintances. Cadfael could not +claim more or better than that.

+ +

“No call to fret,” said the girl briskly. “She’s +over it already, though frightened. In good case to take advice, I hope. +Margery is in there with her.”

+ +

Margery? Of course, the bride! Strange office for +a bride, the day after the wedding, to be nursing her bridegroom’s grandam. +Margery Bele, Cadfael recalled, daughter to the cloth-merchant Edred Bele, had +a very nice little fortune in line for her some day, since she had no brother, +and brought with her a very proper dowry even now. Well worth a miserly +family’s purchase for their heir. But was she, then, so bereft of suitors that +this one offer must buy her? Or had she already seen and wanted that +curly-haired, spoiled, handsome brat now no doubt frowning and fretting over +his losses in the shop here?

+ +

“I must leave her to you and God,” said Susanna. “She +takes no notice of anyone else. And I have the dinner to prepare.”

+ +

“And what of your father?”

+ +

“He’ll do well enough,” she said practically. “He +was very mellow, it did him good service, he fell soft as a cushion. Go along +and see him, when she’s done with you.” She gave him her wry smile, +and slipped away silently down the stairs.

+ +

If Dame Juliana’s attack had affected her speech +at all on this occasion, she had made a remarkable recovery. Flat on her +pillows she might be, and indeed had better remain for a day or so, but her +tongue wagged remorselessly all the time Cadfael was feeling her forehead and +the beat of her heart, and drawing back an eyelid from a fierce grey eye to +look closely at the pupil. He let her run on without response or encouragement, +though he missed nothing of what she had to say.

+ +

“And I expected better of the lord abbot,” she said, +curling thin, bluish lips, “than to take the part of a vagabond footpad, +murderer and thief as he is, against honest craftsmen who pay their dues and +their devotions like Christians. It’s great shame to you all to shelter such a +rogue.”

+ +

“Your son, I’m told,” said Cadfael mildly, +rummaging in his scrip for the little flask of powder dried from oak mistletoe, +“is not dead, nor like to be yet, though the pack of your guests went baying +off through the night yelling murder.”

+ +

“He well might have been a corpse,” she snapped. “And +dead or no, either way this is a hanging matter, as well you know. And how if I +had died, eh? Whose fault would that have been? There could have been two of us +to bury, and the family left ruined into the bargain. Mischief enough for one +wretched little minstrel to wreak in one night. But he’ll pay for it! Forty +days or no, we shall be waiting for him, he won’t escape us.”

+ +

“If he ran from here loaded with your goods,” said +Cadfael, shaking out a little powder into his palm, “he certainly brought none +of them into the church with him. If he has your one miserly penny on him, +that’s all.” He turned to the young woman who stood anxiously beside the head +of the bed. “Have you wine there, or milk? Either does. Stir this into a cup of +it.”

+ +

She was a small, round, homely girl, this Margery, +perhaps twenty years old, with fresh, rosy colouring and a great untidy mass of +yellow hair. Her eyes were round and wary. No wonder if she felt lost in this +unfamiliar and disrupted household, but she moved quietly and sensibly, and her +hands were steady on pitcher and cup.

+ +

“He had time to hide his plunder somewhere,” the +old woman insisted grimly. “Walter was gone above half an hour before Susanna +began to wonder, and went to look for him. The wretch could have been over the +bridge and into the bushes by then.”

+ +

She accepted the drink that was presented to her +lips, and swallowed it down readily. Whatever her dissatisfaction with abbot +and abbey, she trusted Cadfael’s remedies. The two of them were unlikely to +agree on any subject under the sun, but for all that they respected each other. +Even this avaricious, formidable old woman, tyrant of her family and terror of +her servants, had certain virtues of courage, spirit and honesty that were not +to be despised.

+ +

“He swears he never touched your son or your +gold,” said Cadfael. “As I grant he may be lying, so you had better grant that +you and yours may be mistaken.”

+ +

She was contemptuous. She pushed away from under +her wrinkled neck the skimpy braid of brittle grey hair that irritated her +skin. “Who else could it have been? The only stranger, and with a grudge +because I docked him the value of what he broke…”

+ +

“Of what he says some boisterous young fellow +hustled him and caused him to break.”

+ +

“He must take a company as he finds it, wherever +he hires himself out. And now I recall,” she said, “we put him out without +those painted toys of his, wooden rings and balls. I want nothing of his, and +what he’s taken of mine I’ll have back before the end. Susanna will give you +the playthings for him, and welcome. He shall not be able to say we’ve matched +his thievery.”

+ +

She would give him, scrupulously, what was his, +but she would see his neck wrung without a qualm.

+ +

“Be content, you’ve already broken his head for +him. One more blow like that, and you might have had the law crying murder on you. +And you’d best listen to me soberly now! One more rage like that, and you’ll be +your own death. Learn to take life gently and keep your temper, or there’ll be +a third and worse seizure, and it may well be the last.”

+ +

She looked, for once, seriously thoughtful. +Perhaps she had been saying as much to herself, even without his warning. “I am +as I am,” she said, rather admitting than boasting.

+ +

“Be so as long as you may, and leave it to the +young to fly into frenzies over upsets that will all pass, given time. Now here +I’m leaving you this flask—it’s the decoction of heart trefoil, the best thing +I know to strengthen the heart. Take it as I taught you before, and keep your +bed today, and I’ll take another look at you tomorrow. And now,” said Cadfael, +“I’m going along to see how Master Walter fares.”

+ +

The goldsmith, his balding head swathed and his +long, suspicious face fallen slack in sleep, was snoring heavily, and it seemed +the best treatment to let him continue sleeping. Cadfael went down thoughtfully +to find Susanna, who was out in the kitchen at the rear of the house. A skinny +little girl laboured at feeding a sluggish fire and heaving a great pot to the +hook over it. Cadfael had caught a glimpse of the child once before, all great +dark eyes in a pale, grubby face, and a tangle of dark hair. Some poor +maidservant’s by-blow by her master, or her master’s son, or a passing guest. +For all the parsimony in this household, the girl could have fallen into worse +hands. She was at least fed, and handed down cast-off clothing, and if the old +matriarch was grim and frightening, Susanna was quiet and calm, no scold and no +tyrant.

+ +

Cadfael reported on his patient, and Susanna +watched his face steadily, nodded comprehension, and asked no questions.

+ +

“And your father is asleep. I left him so. What better +could anyone do for him?”

+ +

“I fetched his own physician to him last night,” +she said, “when we found him. She’ll have none but you now, but father relies +on Master Arnald, and he’s close. He says the blow is not dangerous, though it +was enough to lay him senseless some hours. Though it may be the drink had something +to do with that, too.”

+ +

“He hasn’t yet been able to tell you what +happened? Whether he saw who the man was who struck him?”

+ +

“Not a word. When he comes to, his head aches so +he can remember nothing. It may come back to him later.”

+ +

For the saving or the damning of Liliwin! But +whichever way that went, and whatever else he might be, Walter Aurifaber was +not a liar. Meantime, there was nothing to be learned from him, but from the +rest of the household there might be, and this girl was the gravest and most +reasonable of the tribe.

+ +

“I’ve heard the general cry against this young +fellow, but not the way the thing happened. I know there was some horse-play with +the lads, nothing surprising at a wedding feast, and the pitcher got broken. I +know your grandmother lashed out at him with her stick, and had him cast out +with only one penny of his fee. His story is that he made off then, knowing it +was hopeless to protest further, and he knew nothing of what followed until he +heard the hunters baying after him, and ran to us for shelter.”

+ +

“He would say so,” she agreed reasonably.

+ +

“Every man’s saying may as well be true as +untrue,” said Cadfael sententiously. “How long after his going was it when Master +Walter went to his workshop?”

+ +

“Nearly an hour it must have been. Some of the +guests were leaving then, but the more lively lads would stay to see Margery +bedded, a good dozen of them were up the stair to the chamber. The wedding +gifts were on the table to be admired, but seeing the night was ending, father +took them and went to lock them away safely in his strong-box in the workshop. +And it must have been about half an hour later, with all the merriment above, +that I began to wonder that he hadn’t come back. There was a gold chain and +rings that Margery’s father gave her, and a purse of silver links, and a breast +ornament of silver and enamel—fine things. I went out by the hall door and +round to the shop, and there he was, lying on his face by the coffer, and the +lid open, and all but the heavy pieces of plate gone.”

+ +

“So the singing lad had been gone a full hour +before this happened. Did anyone see him lurking after he was put out?”

+ +

She smiled, shaking a rueful head. “There was +darkness enough to hide a hundred loiterers. And he did not go so tamely as you +suppose. He knows how to curse, too, he cried us names I’d never heard before, +I promise you, and howled that he’d have his own back for the wrong we did him. +And I won’t say but he was hard done by, for that matter. But who else should +it be? People we’ve known lifelong, neighbours here in the street? No, you may +be sure he hung about the yard in the dark until he saw my father go alone to +the shop, and he stole in there, and saw what wealth there was in the open +coffer. Enough to tempt a poor man, I grant you. But even poor men must needs +resist temptation.”

+ +

“You are very sure,” said Cadfael.

+ +

“I am sure. He owes a life for it.”

+ +

The little maidservant turned her head sharply, +gazing with lips parted. Such eyes, huge and grieved. She made a very small +sound like a kitten’s whimper.

+ +

“Rannilt is daft about the boy,” said Susanna +simply, scornfully tolerant of folly. “He ate with her in the kitchen, and +played and sang for her. She’s sorry for him. But what’s done is done.”

+ +

“And when you found your father lying so, of +course you ran back here to call help for him?”

+ +

“I couldn’t lift him alone. I cried out what had +happened, and those guests who were still here came running, and Iestyn, our +journeyman, came rushing up the stairs from the undercroft where he sleeps—he’d +gone to bed an hour or more earlier, knowing he’d have to man the shop alone +this morning…” Of course, in expectation of the goldsmith’s thick head and his +son’s late tarrying with his bride. “We carried father up to his bed, and +someone—I don’t know who was the first—cried out that this was the jongleur’s +doing, and that he couldn’t be far, and out they all went streaming, every man, +to hunt for him. And I left Margery to watch by father, while I ran off to +fetch Master Arnald.”

+ +

“You did what was possible,” Cadfael allowed. “Then +when was it Dame Juliana took her fit?”

+ +

“While I was gone. She’d gone to her chamber, she +may even have been asleep, though with the larking and laughing in the gallery +I should doubt it. But I was hardly out of the door when she hobbled along to +father’s room, and saw him lying, with his bloody head, and senseless. She +clutched at her heart, Margery says, and fell down. But it was not such a bad +fit this time. She was already wake and talking,” said Susanna, “when I came +back with the physician. We had help then for both of them.”

+ +

“Well, they’ve both escaped the worst,” said +Cadfael, brooding, “for this time. Your father is a strong, hale man, and +should live his time out without harm. But for the dame, more shocks of the +kind could be the death of her, and so I’ve told her.”

+ +

“The loss of her treasury,” said Susanna drily, “was +shock enough to kill her. If she lives through that, she’s proof against all +else until her full time comes. We are a durable kind, Brother Cadfael, very +durable.”

+ +

Cadfael turned aside from leaving by the passage +to the street, and entered Walter Aurifaber’s workshop by the side door. Here +Walter would have let himself in, when he came burdened with several choice +items in gold and silver, enamel and fine stones, to lock them up with his +other wealth in the strong-box; from which, in all likelihood, Mistress Margery +would have had much ado to get them out again for her wearing. Unless, of +course, that soft and self-effacing shape concealed a spirit of unsuspected +toughness. Women can be very deceptive.

+ +

As he entered the shop from the passage, the +street door was on his left, there was a trestled show-table, cloth-covered, and +the rear part of the room was all narrow shelving, the small furnace, cold, and +the work-benches, at which Daniel was working on a setting for a clouded mossa +gate, brows locked in a gloomy knot. But his fingers were deft enough with the +fine tools, for all his preoccupation with the family misfortunes. The +journeyman was bent over a scale on the bench beside the furnace, weighing +small tablets of silver. A sturdy, compact person, this Iestyn, by the look of +him about twenty-seven or twenty-eight years old, with cropped, straight dark +hair in a thick cap. He turned his head, hearing someone entering, and his face +was broad but bony, dark-skinned, thick-browed, deep-eyed, wholly Welsh. A +better-humoured man than his master, though not so comely.

+ +

At sight of Cadfael, Daniel put his tools aside. “You’ve +seen them both? How is it with them?”

+ +

“The pair of them will do well enough for this +time,” said Cadfael. “Master Walter is under his own physician, and held to be +out of any danger, if his memory is shaken. Dame Juliana is over this fit, but +any further shock could be mortal, it’s only to be expected. Few reach such an +age.”

+ +

By the young man’s face, he was pondering whether +any ever should. But for all that, he knew she favoured him, and had a use for +her indulgence. He might even be fond of her, after his fashion, and as far as +affection was possible between sour age and impatient youth. He did not seem +altogether a callous person, only spoiled. Sole heirs of merchant houses can be +as deformed by their privilege as those of baronies.

+ +

In the far corner of the shop Walter’s pillaged +strong-box stood, a big, iron-banded wooden coffer, securely bolted to floor +and wall. Intent on impressing the magnitude of the crime upon any +representative of the abbey that insisted on sheltering the felon, Daniel +unlocked the double locks and heaved up the lid to display what was left +within, a few heavy dishes of plate, too cumbersome to be concealed about the +person. The tale he told, and would tell and retell indignantly as often as he +found a listener, matched Susanna’s account. Iestyn, called to bear witness at +every other aggrieved sentence, could only nod his black head solemnly, and +confirm every word.

+ +

“And you are all sure,” said Cadfael, “that the +jongleur must be the guilty man? No thought of any other possible thief? Master +Walter is known to be a wealthy man. Would a stranger know how wealthy? I +daresay there are some here in the town may well envy a craftsman better-off +than themselves.”

+ +

“That’s a true word,” agreed Daniel darkly. “And +there’s one no farther away than the width of the yard that I might have +wondered about, if he had not been there in my eye every minute of the time. +But he was, and there’s an end. I fancy he was the first to hit on it that it +was the jongleur we wanted.”

+ +

“What, your tenant the locksmith? A harmless soul +enough, I should have thought. Pays his rent and minds his shop, like the +rest.”

+ +

“His man John Boneth minds the shop,” said Daniel, +with a snort of laughter, “and the daft lad helps him. Peche is more often out +poking his long nose into other people’s business, and carrying the gossip +round the ale-houses than tending to his craft. A smiling, sneaking toady of a +man to your face, and back-biting as soon as you turn away. There’s no sneak-thievery +I’d put past him, if you want to know. But he was there in the hall the whole +time, so it was not he. No, make no mistake, we were on the right trail when we +set the pack after that rogue Liliwin, and so it will be proved in the end.”

+ +

They were all in the same story, and the story +might well be true. There was but one point to be put to them counter: where +would a stranger to the town, and out in the dark, stow away so valuable a +booty safely enough and secretly enough to hide it from all others, and yet be +able to recover it himself? The aggrieved family might brush that aside. +Cadfael found it a serious obstacle to belief.

+ +

He was withdrawing by the same door at which he +had entered, and drawing it closed after him by the iron latch, when the draught +of the movement and the lengthening shaft of sunlight piercing the passage +fluttered and illumined a single primrose-coloured thread, waving at the level +of his eyes from the doorpost. The doorpost now on his right, on his left when +he entered, but then out of range of the sun’s rays. Pale as flax, and long and +shining. He took it between finger and thumb, and plucked it gently from the +wood, and a little blotch of dark, brownish red which had gummed it to the post +came away with it, a second, shorter hair coiled and stuck in the blot. Cadfael +stared at it for an instant, and cast one glance back over his shoulder before +he closed the door. From here the coffer in the far corner was plainly in view, +and so would a man be, bending over it.

+ +

A small thing, to make so huge a hole in the +defence a man put up for his life. Someone had stood pressed against that +doorpost, looking in, someone about Cadfael’s own height—a small man with +flaxen hair, and a bloodied graze on the left side of his head.

+
+
+

Chapter Three

+ +

« ^ »

+ +

Saturday, from Noon to Night

+ +

Cadfael was +still standing with the tiny, ominous speck in his palm when he heard his name +called from the hall door, and in the same moment a freshening puff of wind +took the floating hairs and carried them away. He let them go. Why not? They +had already spoken all too eloquently, they had nothing to add. He turned to +see Susanna withdrawing into the hall, and the little maidservant scurrying +towards him, with a knotted bundle of cloth held out before her.

+ +

“Mistress Susanna says, Dame Juliana wants these out of the house.” She +opened the twist of cloth, and showed a glimpse of painted wood, scarred from +much use. “They belong to Liliwin. She said you would take them to him.” The +great dark eyes that dwelt unwaveringly on Cadfael’s face dilated even more. “Is +it true?” she asked, low and urgently. “He’s safe, there in the church? And +you’ll protect him? You won’t let them fetch him away?”

+ +

“He’s with us, and safe enough,” said Cadfael. “No one dare touch him now.”

+ +

“And they haven’t hurt him?” she questioned earnestly.

+ +

“No worse than will mend now, in peace. No need to fret for a while. He has +forty days grace. I think,” he said, studying the thin face, the delicate, +staring cheekbones under the wide-set eyes, “you like this young man.”

+ +

“He made such lovely music,” said the child wistfully. “And he spoke me +gently, and was glad of being with me in the kitchen. It was the best hour I +ever spent. And now I’m frightened for him. What will happen to him when the +forty days are up?”

+ +

“Why, if it goes so far—for forty days is time enough to change many +things—but even if it goes so far, and he must come forth, it will be into the +hands of the law, not into the hands of his accusers. Law is grim enough, but +tries to be fair. And by then those who accuse him will have forgotten their +zeal, but even if they have not, they cannot touch him. If you want to help +him, keep eyes and ears open, and if you learn of anything to the purpose, then +speak out.” Clearly the very thought terrified her. Who ever listened to +anything she might say? “To me you may speak freely,” he said. “Do you know +anything of what went on here last night?”

+ +

She shook her head, casting wary glances over her shoulder. “Mistress +Susanna sent me away to my bed. I sleep in the kitchen, I never even heard… I +was very tired.” The kitchen was set well apart from the house for fear of +fire, as was customary with these close-set and timber-framed town houses, she +might well sleep through all the alarm after her long hours of labour. “But I +do know this,” she said, and lifted her chin gallantly, and he saw that for all +her youth and frailty it was a good chin, with a set to it that he approved. “I +know Liliwin never harmed anyone, not my master nor any other man. What they +say of him is not true.”

+ +

“Nor ever stole?” asked Cadfael gently. She was no way put down, she held +him steadily in her great lamps of eyes. “To eat, yes, perhaps, when he was +hungry, an egg from under a hen somewhere, a partidge in the woods, even a +loaf… that may be. He has been hungry all his life.” She knew, for much of her +life so had she. “But steal more than that? For money, for gold? What good +would that do him? And he is not like that… never!”

+ +

Cadfael was aware of the head emerging from the hall door before Rannilt +was, and warned her softly: “There, run! Say I kept you with questions, and you +knew no answers.”

+ +

She was very quick, she had whirled and was speeding back when Susanna’s +voice pealed impatiently: “Rannilt!”

+ +

Cadfael did not wait to see her vanish within on the heels of her mistress, +but turned at once to resume his way along the passage to the street.

+ +

Baldwin Peche was sitting with a pot of ale on the steps of his shop. The +fact that the street was narrow, and the frontages here faced north-west and +were in deep shadow, suggested that he had a reason beyond idleness and ease +for being where he was at this hour. No doubt all those townsmen who had been guests +at the Aurifaber wedding were up and alert this morning, as soon as they could +shake off the effects of their entertainment, roused and restored by the +sensational gossip they had to spread, and the possibility of further +revelations.

+ +

The locksmith was a man in his fifties; short, sturdy, but beginning to grow +a round paunch, a noted fisherman along the Severn, but a weak swimmer, +unusually for this river-circled town. He had, truly enough, a long nose that +quivered to every breath of scandal, though he was cautious in the use he made +of it, as though he enjoyed mischief for its own sake rather than for any +personal profit. A cold, inquisitive merriment twinkled in his pale-blue eyes, +set in, a round, ruddy and smiling face. Cadfael knew him well enough to pass +the time of day, and gave him good morrow as though making the approach +himself, whereas he was well apprised Peche had been waiting to make it.

+ +

“Well, Brother Cadfael,” said the locksmith heartily, “you’ll have been +tending these unlucky neighbours of mine. I trust you find them bearing up +under their griefs? The lad tells me they’ll make good recoveries, the both of +them.”

+ +

Cadfael said what was required of him, which was rather enquiry than +response, and kept his mouth shut and his ears open to listen to the tale all +over again, with more and richer detail, since this was Peche’s chosen craft. +The journeyman locksmith, a fine-looking young man who lived with his widowed +mother a street or two away in the town, looked out once from the shop doorway, +cast a knowledgeable eye on his master, and withdrew, assured of having work to +himself, as he preferred it. By this time John Boneth knew everything his +skilled but idle tutor could teach him, and was quite capable of running the +business single-handed. There was no son to inherit it, he was trusted and +depended on, and he could wait.

+ +

“A lucky match, mark,” said Peche, prodding a knowing finger into Brother +Cadfael’s shoulder, “especially if this treasury of Walter’s is really lost, +and can’t be recovered. Edred Bele’s girl has money enough coming to her to +make up the half, at least. Walter’s worked hard to get her for his lad, and +the old dame’s done her share, too. Trust them!” He rubbed finger and thumb +together suggestively, and nudged and winked. “And the girl no beauty and +without graces—neither sings nor dances well, and dumb in company. No monster, +though, she’ll pass well enough, or that youngster would never have been +brought to… not with what he has in hand!”

+ +

“He’s a fine-looking lad,” said Cadfael mildly, “and they say not unskilled. +And a good inheritance waiting for him.”

+ +

“Ah, but short now! +whispered Baldwin, leaning closer still and stabbing with a stiff forefinger, +his knowing face gleeful. “It’s the waiting is hard to bear. Young folk live +now, not tomorrow, and this side marriage—you take my meaning?—not t’other. Oh, +the old dame may dote on him, the sun shines out of his tail for her, but she +keeps her hold on the purse and doles out sweets very sparingly. Not enough for +the sort he fancies!”

+ +

It occurred to Cadfael, rather belatedly, that it was hardly becoming +behaviour in one of his habit to listen avidly to local scandal, but if he did +nothing to encourage confidences, he certainly did not stop listening. +Encouragement, in any case, was unnecessary. Peche had every intention of +making the most of his probings.

+ +

“I wouldn’t say,” he breathed into Cadfael’s ear, “but he’s had his fingers +in her purse a time or two, for all her sharpness. His present fancy comes +expensive, not to speak of the game there’ll be if ever her husband gets to +know of their cantrips. It’s a fair guess the bride’s dowry, as much of it as +he can get his hands on, will go to deck out another wench’s neck. Not that he +had any objections to this match—not he, he likes the girl well enough, and he +likes her money a good deal better. But he likes somebody else best of all. No +names, no revenges! But you should have seen her as a guest last night! Bold as +a royal whore, and the old man puffed up beside her, proud of owning the +handsomest thing in the hall, and she and the bridegroom eyeing each other fit +to laugh out loud at the old fool. As well I was the only one there had sharp +enough eyes to see the sparks pass!”

+ +

“As well, indeed!” said Cadfael almost absently, for he was busy reflecting +how understandable it was that Daniel should view his father’s tenant with such +ill-will. No need to doubt Peche’s information, really devoted pryers make sure +of their facts. Doubtless, though never a word need have been said, certain quiverings +of that inquisitive nose and knowing glances from those coldly merry eyes had +warned Daniel, evidently not quite a fool, that his gallivantings were no +secret.

+ +

And the other, the old fool, welcome guest at the wedding—of consequence, +therefore, among the merchants of Shrewsbury and with a young, bold, handsome +wife… A second marriage, then, on the man’s part? The town was not so great +that Cadfael had to look very far. Ailwin Corde, widowed a few years ago and +married again, against his grown son’s wishes, to a fine, flaunting beauty a +third his age, called Cecily…

+ +

“I’d keep your tongue within your teeth,” he advised amiably. “Wool +merchants are a power in this town, and not every husband will thank you for +opening his eyes.”

+ +

“What, I? Speak out of turn?” The merry eyes sparkled with all the +cordiality of ice, and the long nose twitched. “Not I! I have a decent landlord +and a snug corner, and no call to overturn what suits me well. I take my fun +where I find it, Brother, but quietly and privately. No harm in what does +none.”

+ +

“None in the world,” agreed Cadfael, and took his leave peaceably, and went +on towards the winding descent of the Wyle, very thoughtful, but none too sure +of what he should be thinking. For what had he learned? That Daniel Aurifaber +was paddling palms, and probably more, with mistress Cecily Corde, whose +wool-merchant husband collected fleeces from the bordering district of Wales, +and traded them into England, and therefore was often absent for some days at a +time, and that the lady, however fond, was accustomed to gifts, and did not +come cheaply, whereas the young man was baulked by equally parsimonious father +and grandmother, and was reputed already to be filching such small sums as he +could get his fingers on. And no easy matter, either! And had his father not +gone to lock up at least half of the bride’s dowry out of reach? Out of reach +now in good earnest—or had last night’s events snugged it away well within +reach? Such things can happen in families.

+ +

What else? That Daniel held no good opinion, reasonably enough, of the +tenant who spent his leisure so inconveniently, and claimed he would have held +him to be a prime suspect, if he had not been in full view throughout the time +when the deed was done.

+ +

Well, time would show. They had forty days in hand.

+ +

High Mass was over when Cadfael had crossed the bridge and made his way back +to the gatehouse and the great court. Prior Robert’s shadow, Brother Jerome, +was hovering in the cloister to intercept him when he came.

+ +

“The lord abbot asks that you will wait upon him before dinner.” Jerome’s +pinched, narrow nose quivered with a suggestion of deprecation and distaste +which Cadfael found more offensive than Baldwin Peche’s full-blooded enjoyment +of his own mischief. “I trust, Brother, that you mean to let time and law take +their course, and not involve our house beyond the legal obligations of +sanctuary, in so sordid a matter. It is not for you to take upon yourself the burdens +that belong to justice.”

+ +

Jerome, if he had not explicit orders, had received his charge from Prior +Robert’s knotted brow and quivering nostril. So low and ragged and miserable a +manifestation of humanity as Liliwin, lodged here within the pale, irked Robert +like a burr working through his habit and fretting his aristocratic skin. He +would have no peace while the alien body remained, he wanted it removed, and +the symmetry of his life restored. To be fair, not merely his own life, but the +life of this house, which fretted and itched with the infection thus hurled in +from the world without. The presence of terror and pain is disruptive indeed.

+ +

“All the abbot wants from me is an account of how my patients fare,” said +Cadfael, with unwonted magnanimity towards the narrow preoccupations of +creatures so uncongenial to him as Robert and his clerk. For their distress, +however strange to him, was still comprehensible. The walls did, indeed, +tremble, the sheltered souls did quake. “And I have burdens enough with them, +and am hardly looking for any others. Is that lad fed and doctored? That’s all +my business with him.”

+ +

“Brother Oswin has taken care of him,” said Jerome.

+ +

“That’s well! Then I’ll go pay my respects to the lord abbot, and get to my +dinner, for I missed breakfast, and those up there in the town are too +distraught to think of offering a morsel.”

+ +

He wondered, however, as he crossed the court to the abbot’s lodging, how +much of what he had gleaned he was about to impart. Salacious gossip can be of +no interest to abbatial ears, nor was there much to be said about a tiny plaque +of dried blood tethering a couple of flaxen hairs; not, at least, until the +vagabond, with every hand against him and his life at stake, had exercised the +right to answer for himself.

+ +

Abbot Radulfus received without surprise the news that the entire wedding +party was united in insisting on the jongleur’s guilt. He was not, however, +quite convinced that Daniel, or any other of those attending could be certain +who had, or had not, been in full view throughout.

+ +

“With a hall full of so many people, so much being drunk, and over so many +hours of celebration, who can say how any man came and went? Yet so many voices +all in one tale cannot be disregarded. Well, we must do our part, and leave the +law to deal with the rest. The sergeant tells me his master the sheriff is gone +to arbitrate in a dispute between neighbour knights in the east of the shire, +but his deputy is due in the town before night.”

+ +

That was good news in Cadfael’s ear. Hugh Beringar would see to it that the +search for truth and justice should not go sliding down the easiest way, and +erase such minor details as failed to fit the pattern. Meantime, Cadfael had +just such a detail to take up with Liliwin, besides restoring him the tools of +his juggling trade. After dinner he went to look for him, and found him sitting +in the cloister, with borrowed needle and thread, trying to cobble together the +rents in his coat. Beneath the bandaged brow he had washed his face scrupulously, +it showed pale and thin but clear-skinned, with good, even delicate features. +And if he could not yet wash the dust and mire from his fair hair, at least he +had combed it into decent order.

+ +

The sop first, perhaps, and then the switch! Cadfael sat down beside him, +and dumped the cloth bundle in his lap. “Here’s a part of your property restored +you, for an earnest. There, open it!”

+ +

But Liliwin already knew the faded wrapping. He sat gazing down for a moment +in wonder and disbelief, and then untied the knotted cloth and sank his hand +among his modest treasures with affection and pleasure, faintly flushing and +brightening, as though for the first time recovering faith that some small +comforts and kindnesses existed for him in the world.

+ +

“But how did you get them? I never thought I should see them again. And you +thought to ask for them… for me… That was kind!”

+ +

“I did not even have to ask. That old dame who struck you, terror though she +may be, is honest. She won’t keep what is not hers, if she won’t forgo a groat +of what is. She sends them back to you.” Not graciously, but no need to go into +that. “There, take it for a good sign. And how do you find yourself today? Have +they fed you?”

+ +

“Very well! I’m to fetch my food from the kitchen at breakfast, dinner and +supper.” He sounded almost incredulous, naming three meals a day. “And they’ve +given me a pallet in the porch here. I’m afraid to be away from the church at +night.” He said it simply and humbly. “They don’t all like it that I’m here. I +stick in their craw like a husk.”

+ +

“They’re accustomed to calm,” said Cadfael sympathetically. “It is not calm +you bring. You must make allowances, as they must. At least from tonight you +may sleep secure. The deputy sheriff should be in town by this evening. In his +authority, I promise you, you can trust.”

+ +

Trust would still come very hardly to Liliwin, after all he had experienced +in a short life, but the toys he had tucked away so tenderly under his pallet +were a promise. He bent his head over his patient stitching, and said no word.

+ +

“And therefore,” said Cadfael briskly, “You’d best consider on the half-tale +you told me, and own to the part you left out. For you did not creep away so +docilely as you let us all think, did you? What were you doing, hugging the +door-post of Master Walter’s workshop, long after you claim you had made off +into the night? With the door open, and your head against the post, and the +goldsmith’s coffer in full view… and also open? And he bending over it!”

+ +

Liliwin’s needle had started in his fingers and pricked his left hand. He +dropped needle, thread and coat, and sat sucking his pierced thumb, and staring +at Brother Cadfael with immense, frightened eyes. He began to protest shrilly: +“I never went there… I know nothing about it…” Voice and eyes sank together. He +blinked down at his open hands, lashes long and thick as a well-bred cow’s brushing +his staring cheekbones.

+ +

“Child,” said Cadfael, sighing, “you were there in the doorway, peering in. +You left your mark there. A lad your size, with a bloodied head, leaned long +enough against that door-post to leave a little clot of his blood, and two +flax-white hairs gummed into it. No, no other has seen it, it’s gone, blown +away on the wind, but I saw it, and I know. Now tell me truth. What passed +between you and him?”

+ +

He did not ask why Liliwin had lied in omitting this part of his story, +there was no need. What, place himself there on the spot, there were the blow +had been struck? Innocence would have avoided admission every bit as +desperately as guilt.

+ +

Liliwin sat and shivered, fluttering like a leaf in that same wind which had +carried off his stray hairs. Here in the cloister the air was still chilly, and +he had only a patched shirt and hose on him, the half-mended coat lying on his +knees. He swallowed hard and sighed.

+ +

“It’s true, I did wait… It was not fair!” he blurted, shaking. “I stayed +there in the dark. They were not all as hard as she, I thought I might plead… I +saw him go to the shop with a light and I followed. He was not so furious when +the pitcher was broken, he did try to calm her, I dared approach him. I went in +and pleaded for the fee I was promised, and he gave me a second penny. He gave +it to me and I went. I swear it!”

+ +

He had sworn the other version, too. But fear does so, the fear bred of a +lifetime’s hounding and battering.

+ +

“And then you left? And you saw no more of him? More to the point still, did +you see ought of any other who may have been lurking as you did, and entered to +him afterwards?”

+ +

“No, there was no one. I went, I was glad to go, it was all over. If he +lives, he’ll tell you he gave me the second penny.”

+ +

“He lives, and will,” said Cadfael. “It was not a fatal blow. But he’s said +nothing yet.”

+ +

“But he will, he will, he’ll tell you how I begged him, and how he took pity +on me. I was afraid,” he said quivering, “I was afraid! If I’d said I went +there, it would have been all over with me.”

+ +

“Well, but consider,” said Cadfael reasonably, “when Walter is his own man +again, and comes forth with that very tale, how would it look if he brought it +out when you had said no word of it? And besides, when his wits settle and he +recalls what befell, it may well be that he’ll be able to name his attacker, +and clear you of all blame.”

+ +

He was watching closely as he said it, for to an innocent man that notion +would come as powerful comfort, but to a guilty one as the ultimate terror; and +Liliwin’s troubled countenance gradually cleared and brightened into timid +hope. It was the first truly significant indication of how far he should be +believed.

+ +

“I never thought of that. They said murdered. A murdered man can’t accuse or +deliver. If I’d known then he was well alive I would have told the whole truth. +What must I do now? It will look bad to have to own I lied.”

+ +

“What you should do for the best,” Cadfael said after some thought, “is let +me take this word myself to the lord abbot, not as my discovery—for the +evidence is gone with a puff of wind—but as your confession. And if Hugh +Beringar comes tonight, as I hope and hear he may, then you may tell the tale +over again to him in full, yourself. Whatever follows then, you may rest out +your days of grace here with a clear conscience and truth will speak on your +side.”

+ +

Hugh Beringar of Maesbury, deputy sheriff of the shire, reached the abbey +for Vespers, after a long conference with the sergeant concerning the lost +treasury. In search of it, every yard of ground between the goldsmith’s house +and the bushes from which Liliwin had been flushed at midnight had been scoured without result. Every voice in the town declared confidently that the +jongleur was the guilty man, and had successfully hidden his plunder before he +was sighted and pursued.

+ +

“But you, I think,” said Beringar, walking back towards the gatehouse with +Cadfael beside him and twitching a thin dark eyebrow at his friend, “do not +agree. And not wholly because this enforced guest of yours is young and hungry +and in need of protection. What is it convinces you? For I do believe you are +convinced he’s wronged.”

+ +

“You’ve heard his story,” said Cadfael. “But you did not see his face when I +put it into his head that the goldsmith may get back his memory of the night in +full, and be able to put a name or a face to his assailant. He took that hope +to him like a blessed promise. The guilty man would hardly do so.”

+ +

Hugh considered that gravely and nodded agreement. “But the fellow is a +player, and has learned hard to keep command of his face in all circumstances. +No blame to him, he has no other armour. To appear innocent of all harm must +now be his whole endeavour.”

+ +

“And you think I am easily fooled,” said Cadfael drily.

+ +

“Far from it. Yet it is well to remember and admit the possibility.” And +that was also true, and Hugh’s dark smile, slanted along his shoulder, did +nothing to blunt the point. “Though I grant it would be nothing new for you to +be the only creature who holds against the grain, and makes his wager good.”

+ +

“Not the only one,” said Cadfael almost absently, with Rannilt’s wan, elfin +face before his mind’s eye. “There’s one other more certain than I.” They had +reached the arch of the gatehouse, the broad highway of the Foregate crossed +beyond, and the evening was just greening and dimming towards twilight. “You +say you found the place where the lad bedded down for the night? Shall we take +a look there together?”

+ +

They passed through the arch, an odd pair to move so congenially side by +side, the monk squat and square and sturdy, rolling in his gait like a seaman, +and well launched into his sixtieth year, the sheriff’s deputy more than thirty +year younger and half a head taller, but still a small man, of graceful, nimble +movements and darkly saturnine features. Cadfael had seen this young man win +his appointment fairly, and a wife to go with it, and had witnessed the +christening of their first son only a few months ago. They understood each +other better than most men ever do, but they could still take opposing sides in +a matter of the king’s justice.

+ +

They turned towards the bridge that led into the town, but turned aside +again on the right, a little way short of the riverside, into the belt of trees +that fringed the road. Beyond, towards the evening gleam of the Severn, the +ground declined to the lush level of the main abbey gardens, along the meadows +called the Gaye. They could see the green, clear light through the branches as +they came to the place where Liliwin had settled down sadly to sleep before +leaving this unfriendly town. And it was a nest indeed, rounded and coiled into +the slope of thick new grass, and so small, like the haunt of a dormouse.

+ +

“He started up in alarm, in one leap clear of his form, like a flushed +hare,” said Hugh soberly. “There are young shoots broken here—do you see?—where +he crashed through. This is unquestionably the place.” He looked round +curiously, for Cadfael was casting about among the bushes, which grew thickly +here for cover. “What are you seeking?”

+ +

“He had his rebec in a linen bag on his shoulder,” said Cadfael. “In the +dark a branch caught the string and jerked it away, and he dared not stop to +grope after it. So he told me, like a man bereaved. I am sure that was truth. I +wonder what became of it?”

+ +

He found the answer that same evening, but not until he had parted from Hugh +and was on his way back to the gatehouse. It was a luminous evening and Cadfael +was in no hurry to go in, and had plenty of time before Compline. He stood to +watch the leisurely evening walk of the Foregate worthies, and the prolonged +games of the urchins of the parish of Holy Cross reluctant to go home to their +beds, just as he was. A dozen or so of them swept by in a flurry of yelling and +laughter, shrill as starlings, some still half-naked from the river, but not +yet so cold that they must make for the home hearth. They were kicking a +shapeless rag ball among them, and some of them swiping at it with sticks, and +one with something broader and shorter. Cadfael heard the impact of hollow +wood, and the thrumming reverberation of one surviving string. A lamentable +sound, like a cry for help with little expectation that the plea would be +heard.

+ +

The imp with this weapon loitered, dragging his implement in the dust. +Cadfael pursued, and drew alongside like a companion ship keeping station +rather than a pirate boarding. The brat looked up and grinned, knowing him. He +had but a short way to go home, and was tired of his plaything.

+ +

“Now what in the world have you found there?” said Cadfael amicably. “And +where did you happen on such an odd thing?”

+ +

The child waved a hand airily back towards the trees that screened the Gaye. +“It was lying in there, in a cloth bag, but I lost that down by the water. I +don’t know what it is. I never saw a thing like it. But it’s no use that I can +see.”

+ +

“Did you find,” asked Cadfael, eyeing the wreckage, “a stick, with fine +hairs stretched along it, that went with this queer thing?”

+ +

The child yawned, halted, and abandoned his hold on his toy, letting it drop +into the dust. “I hit Davey with that when he tripped me in the water, but it +broke. I threw it away.” So he would, having proved its uselessness, just as he +walked away from this discarded weapon, leaving it lying, and went off +scrubbing at sleepy eyes with the knuckles of a grimy fist.

+ +

Brother Cadfael picked up the sorry remnant and examined ruefully its +stove-in ribs and trailing, tangled strings. No help for it, this was all that +remained of the lost rebec. He took it back with him, only too well aware of +the grief he was about to cause its luckless owner. Say that Liliwin came alive +in the end out of his present trouble, still he must emerge penniless, and +deprived now even of his chief means of livelihood. But there was more in it +even than that. He knew it even before he presented the broken instrument to +Liliwin’s appalled hands, and watched the anguish and despair mantle like bleak +twilight over his face. The boy took the ruin in his hands and fondled it, +rocked it in his arms, bowed his head to its splintered frame, and burst into +tears. It was not the loss of a possession so much as the death of a +sweetheart.

+ +

Cadfael sat down apart, in the nearest carrel of the scriptorium, and kept +decently silent until the storm passed, and Liliwin sat drained and motionless, +hugging his broken darling, his thin shoulders hunched against the world.

+ +

“There are men,” said Cadfael then mildly, “who understand such arts as +repairing instruments of music. I am not one of them, but Brother Anselm, our +precentor, is. Why should we not ask him to look at your fiddle and see what +can be done to make it sing again?”

+ +

This?” Liliwin turned on him passionately, holding out the +pathetic wreck in both hands. “Look at it—no better than firewood. How could +anyone restore it?”

+ +

“Do you know that? Do I? What’s lost by asking the man who may? And if this +is past saving, Brother Anselm can make one new.”

+ +

Bitter disbelief stared back at him. Why should he credit that anyone would +go out of his way to do a kindness to sod espised and unprofitable a creature +as himself? Those within here held that they owed him shelter and food, but +nothing more, and even that as a duty. And no one without had ever offered him +any benefit that cost more than a crust.

+ +

“As if I could ever pay for a new one! Don’t mock me!”

+ +

“You forget, we do not buy and sell, we have no use for money. But show +Brother Anselm a good instrument damaged, and he’ll want to heal it. Show him a +good musician lost for want of an instrument, and he’ll be anxious to provide +him a new voice. Are you a good musician?”

+ +

Liliwin said: “Yes!” with abrupt and spirited pride. In one respect, at +least, he knew his worth.

+ +

“Then show him you are, and he’ll give you your due.”

+ +

“You mean it?” wondered Liliwin, shaken between hope and doubt. “You will +truly ask him? If he would teach me, perhaps I could learn the art.” He +faltered there, losing his momentary brightness with a suddenness that was all +too eloquent. Whenever he took heart for the future, the bleak realisation came +flooding over him afresh that he might have no future. Cadfael cast about +hurriedly in his mind for some crumb of distraction to ward off the recurrent +despair.

+ +

“Never suppose that you’re friendless, that’s black ingratitude when you +have forty days of grace, a fair-minded man like Hugh Beringar enquiring into +your case, and one creature at least who stands by you stoutly and won’t hear a +word against you.” Liliwin kindled a little at that, still doubtfully, but at +least it had put the gallows and the noose out of his mind for the moment. “You’ll +remember her—a girl named Rannilt.”

+ +

Liliwin’s face at once paled and brightened. It was the first smile Cadfael +had yet seen from him, and even now tentative, humble, frightened to reach for +anything desired, for fear it should vanish like melting snow as he clutched +it.

+ +

“You’ve seen her? Talked to her? And she does not believe what they all say +of me?”

+ +

“Not a word of it! She affirms—she knows— you never did violence nor +theft in that house. If all the tongues in Shrewsbury cried out against you, +she would still stand her ground and speak for you.”

+ +

Liliwin sat cradling his broken rebec, as gently and shyly as if he clasped +a sweetheart indeed. His faint, frightened smile shone in the dimming light +within the cloister.

+ +

“She is the first girl who ever looked kindly at me. You won’t have heard +her sing—such a small, sweet voice, like a reed. We ate in the kitchen +together. It was the best hour of my life, I never thought… And it’s true? +Rannilt believes in me?”

+
+
+

Chapter Four

+ +

« ^ »

+ +

Sunday

+ +

Liliwin folded +away his brychans and made himself presentable before Prime on the sabbath, +determined to cause as little disruption as possible in the orderly regime +within these walls. In his wandering life he had had little opportunity to +become familiar with the offices of the day, and Latin was a closed book to +him, but at least he could attend and pay his reverences, if that would make +him more acceptable.

+ +

After breakfast Cadfael dressed the gash in the young man’s arm again, and +unwound the bandage from the graze on his head. “This is healing well,” he said +approvingly. “We’d best leave it uncovered, and let in the air to it now. Good +clean flesh you have, boy, if something too little of it. And you’ve lost that +limp that had you going sidewise. How is it with all those bruises?”

+ +

Liliwin owned with some surprise that most of his aches and pains were all +but gone, and performed a few startling contortions to prove it. He had not +lost his skills. His fingers itched for the coloured rings and balls he used +for his juggling, safely tucked away in their knotted cloth under his bed, but +he feared they would be frowned on here. The ruin of his rebec also reposed in +the corner of the porch next the cloister. He returned there after his +breakfast to find Brother Anselm turning the wreck thoughtfully in his hands, +and running a questing finger along the worst of the cracks.

+ +

The precentor was past fifty, a vague, slender, shortsighted person who peered +beneath an untidy brown tonsure and bristling brows to match, and smiled +amiably and encouragingly at the owner of this disastrous relic.

+ +

“This is yours? Brother Cadfael told me how it had suffered. This has been a +fine instrument. You did not make it?”

+ +

“No. I had it from an old man who taught me. He gave it to me before he +died. I don’t know,” said Liliwin, “how to make them.”

+ +

It was the first time Brother Anselm had heard him speak since the shrill +terror of the first invasion. He looked up alertly, tilting his head to listen. +“You have the upper voice, very true and clear. I could use you, if you sing? +But you must sing! You have not thought of taking the cowl, here among us?” He +recalled with a sigh why that was hardly likely under present circumstances. “Well, +this poor thing has been villainously used, but it is not beyond help. We may +try. And the bow is lost, you say.” Liliwin had said no such thing, he was mute +with wonder. Evidently Brother Cadfael had given precise information to a +retentive enthusiast. “The bow, I must say, is almost harder to perfect than +the fiddle, but I have had my successes. Have you skills on other instruments?”

+ +

“I can get a tune out of most things,” said Liliwin, charmed into eagerness.

+ +

“Come,” said Brother Anselm, taking him firmly by the arm, “I will show you +my workshop and you and I between us, after High Mass, will try what can best +be done for this rebec of yours. I shall need a helper to tend my resins and +gums. But this will be slow and careful work, mind, and matter for prayer, not +to be hastened for any cause. Music is study for a lifetime, son—a lifetime +however long.”

+ +

He blew so like a warm gale that Liliwin went with him in a dream, +forgetting how short a lifetime could also be.

+ +

Walter Aurifaber woke up that morning with a lingering headache, but also +with a protesting stiffness in his limbs and restless animation in his mind +that made him want to get up and stretch, and stamp, and move about briskly +until the dullness went out of him. He growled at his patient, silent daughter, +enquired after his journeyman, who had had the sense to make sure of his Sunday +rest by vanishing from both shop and town for the day, and sat down to eat a +substantial breakfast and stare his losses in the face.

+ +

Things were coming back to him, however foggily, including one incident he +would just as soon his mother should not hear about. Money was money, of +course, the old woman had the right of it there, but it’s not every day a man +marries off his heir, and marries him, moreover, to a most respectable further +amount of money. A little flourish towards a miserable menial might surely be +forgiven a man, in the circumstances. But would she think so? He regretted it +bitterly himself, now, reflecting on the disastrous result of his rare impulse +of generosity. No, she must not hear of it!

+ +

Walter nursed his thick head and vain regrets, and took some small comfort +in seeing his son and his new daughter-in-law off to church at Saint Mary’s, in +their best clothes and properly linked, Margery’s hand primly on Daniel’s arm. +The money Margery had brought with her, and would eventually bring, mattered +now more than anything else until the lost contents of his strong-box could be +recovered. His head ached again fiercely when he thought of it. Whoever had +done that to the house of Aurifaber should and must hang, if there was any +justice in this world.

+ +

When Hugh Beringar came, with a sergeant in attendance, to hear for himself +what the aggrieved victim had to tell, Walter was ready and voluble. But he was +none too pleased when Dame Juliana, awaiting Brother Cadfael’s visit, and +foreseeing more strictures as to her behaviour if she wanted to live long, took +it into her head to forestall the lecture by being downstairs when her mentor +came and stumped her way down, cane in hand, prodding every tread before her +and scolding Susanna away from attempting to check her. She was firmly settled +on her bench in the corner, propped with cushions, when Cadfael came, and +challenged him with a bold, provocative stare. Cadfael chose not to gratify her +with homilies, but delivered the ointment he had brought for her, and reassured +himself of the evenness of her breathing and heart, before turning to a Walter +grown unaccountably short of words.

+ +

“I’m glad to see you so far restored. The tales they told of you were twenty +years too soon. But I’m sorry for your loss. I hope it may yet be recovered.”

+ +

“Faith, so do I,” said Walter sourly. “You tell me that rogue you have in +sanctuary has no part of it on him, and while you hold him fast within there he +can hardly unearth and make off with it. For it must be somewhere, and I trust +the sheriff’s men here to find it.”

+ +

“You’re very certain of your man, then?” Hugh had got him to the point where +he had taken his valuables and gone to stow them away in the shop, and there he +had suddenly grown less communicative. “But he had already been expelled some +time earlier, as I understand it, and no one has yet testified to seeing him +lurking around your house after that.”

+ +

Walter cast a glance at his mother, whose ancient ears were pricked and her +faded but sharp eyes alert. “Ah, but he could well have stayed in hiding, all +the same. What was there to prevent it in the dark of the night?”

+ +

“So he could,” agreed Hugh unhelpfully, “but there’s no man so far claims he +did. Unless you’ve recalled something no one else knows? Did you see +anything of him after he was thrown out?”

+ +

Walter shifted uneasily, looked ready to blurt out a whole indictment, and +thought better of it in Juliana’s hearing. Brother Cadfael took pity on him.

+ +

“It might be well,” he said guilelessly, “to take a look at the place where +this assault was made. Master Walter will show us his workshop, I am sure.”

+ +

Walter rose to it thankfully, and ushered them away with alacrity, along the +passage and in again at the door of his shop. The street door was fast, the day +being Sunday, and he closed the other door carefully behind them, and drew +breath in relief.

+ +

“Not that I’ve anything to conceal from you, my lord, but I’d as lief my +mother should not have more to worry her than she has already.” Plausible +cover, at any rate, for the awe of her in which he still went. “For this is +where the thing happened, and you see from this door how the coffer lies in the +opposite corner. And there was I, with the key in the lock and the lid laid +back against the wall, wide open, and my candle here on the shelf close by. The +light shining straight down into the coffer—you see?—and what was within in +plain view. And suddenly I hear a sound behind me, and there’s this minstrel, +this Liliwin, creeping in at the door.”

+ +

“Threateningly?” asked Hugh, straight-faced. If he did not wink at Cadfael, +his eyebrow was eloquent. “Armed with a cudgel?”

+ +

“No,” admitted Walter, “rather humbly, to all appearance. But then I’d heard +him and turned. He was barely into the doorway, he could have dropped his +weapon outside when he saw I was ware of him.”

+ +

“But you did not hear it fall? Nor see any sign of such?”

+ +

“No, that I own.”

+ +

“Then what had he to say to you?”

+ +

“He begged me to do him right, for he said he had been cheated of two thirds +of his promised fee. He said it was hard on a poor man to be so blamed and +docked of his money, and pleaded with me to make it good as promised.”

+ +

“And did you?” asked Hugh.

+ +

“I tell you honestly, my lord, I could not say he had been hardly used, +considering the worth of the pitcher, but I did think him a poor, sad creature +who had to live, whatever the rights or wrongs of it. And I gave him another +penny—good silver, minted in this town. But not a word of this to Dame Juliana, +if you’ll be so good. She’ll have to know, now it’s all come back to me, that +he dared creep in and ask, but no need for her to know I gave him anything. She +would be affronted, seeing she had denied him.”

+ +

“Your thought for her does you credit,” said Hugh gravely. “What then? He took +your bounty and slunk out?”

+ +

“He did. But I wager he has not told you anything of this begging +visit. A poor return I got for the favour!” Walter was sourly vengeful still.

+ +

“You mistake, for he has. He has told us this very same tale that you now +tell. And confided to the abbey’s keeping, while he remains there, the two +silver pence which is all he has on him. Tell me, had you closed the lid of the +coffer as soon as you found yourself observed?”

+ +

“I did!” said Walter fervently. “And quickly! But he had seen. I never gave +him another thought at the time but—see here, my lord, how it follows! As soon +as he was gone, or I thought he was gone, I opened the coffer again, and was +bending over it laying Margery’s dowry away, when I was clouted hard from +behind, and that’s the last I knew till I opened an eye in my own bed, hours +later. If it was two minutes after that fellow crept out of the door, when +someone laid me flat, it was not a moment more. So who else could it be?”

+ +

“But you did not actually see who struck you?” Hugh pressed. “Not +so much as a glimpse? No shadow cast, to give him a shape or size? No sense of +a bulk heaving up behind you?”

+ +

“Never a chance.” Walter might be vindictive, but he was honest. “See, I was +stooping over the coffer when it seemed the wall fell on me, and I pitched +asprawl, head-down into the box, clean out of the world. I heard nothing and +saw nothing, not even a shadow, no—the last thing I recall was the candle +flickering, but what is there in that? No, depend on it, that rogue had seen +what I had in my store before I clapped down the lid. Was he going tamely away +with his penny, with all that money there to take? Not he! Nor hide nor hair of +any other did I see in here that night. You may be certain of it, the jongleur +is your man.”

+ +

“And it may still be so,” admitted Hugh, parting from Cadfael on the bridge +some twenty minutes later. “Enough to tempt any poor wretch with but two coins +to rub together. Whether he had any such thought in his head before the candle +shone on our friend’s hoard or no. Equally, I grant the lad may not even have +realised what lay beneath his hand, or seen anything but his own need and the +thin chance of getting a kinder reception from the goldsmith than from that +ferocious mother of his. He may have crept away thanking God for his penny and +never a thought of wrong. Or he may have picked up a stone or a stave and +turned back.”

+ +

At about that same time, in the street outside Saint Mary’s church, which +was the common ground for exchanging civilities and observing fashions on a +fine Sunday morning after Mass, Daniel and Margery Aurifaber in their +ceremonial progression, intercepted by alternate well-wishers and +commiserators—wedding and robbery being equally relished subjects of comment +and speculation in Shrewsbury—came face to face with Master Ailwin Corde, the +wool-merchant, and his wife, Cecily, and halted by general consent to pass the +time of day as befitted friends and neighbours.

+ +

This Mistress Cecily looked more like a daughter to the merchant, or even a +granddaughter, than a wife. She was twenty-three years old to his sixty, and +though small and slender of stature, was so opulent in colouring, curvature and +gait, and everything that could engage the eye, that she managed to loom large +as a goddess and dominate whatever scene she graced with her presence. And her +elderly husband took pleasure in decking her out with sumptuous fabrics and +fashions the gem he should rather have shrouded in secretive, plain linens. A +gilt net gathered on her head its weight of auburn hair, and a great ornament +of enamel and gemstones jutted before her, calling attention to a resplendent +bosom.

+ +

Faced with this richness, Margery faded, and knew that she faded. Her smile +became fixed and false as a mask, and her voice tended to sharpen like a singer +forced off-key. She tightened her clasp on Daniel’s arm, but it was like trying +to hold a fish that slid through her fingers without even being aware of +restraint.

+ +

Master Corde enquired solicitously after Walter’s health, was relieved to +hear that he was making a good recovery, was sad, nonetheless, to know that so +far nothing had been found of all that had been so vilely stolen. He sent his +condolences, while thanking God for life and health spared. His wife echoed all +that he said, modest eyes lowered, and voice like distant wood-doves.

+ +

Daniel, his eyes wandering more often to Mistress Cecily’s milk-and-roses +face than to the old man’s flabby and self-satisfied countenance, issued a +hearty invitation to Master Corde to bring his wife and take a meal with the +goldsmith as soon as might be, and cheer him by his company. The wool-merchant +thanked him, and wished it no less, but must put off the pleasure for a week or +more, though he sent his sympathetic greetings and promised his prayers.

+ +

“You don’t know,” confided Mistress Cecily, advancing a small hand to touch +Margery’s arm, “how fortunate you are in having a husband whose trade is rooted +fast at home. This man of mine is for ever running off with his mules and his +wagon and his men, either west into Wales or east into England, over business +with these fleeces and cloths of his, and I’m left lonely days at a time. Now +tomorrow early he’s off again, if you please, as far as Oxford, and I shall +lack him for three or four days.”

+ +

Twice she had raised her creamy eyelids during this complaint, once ruefully +at her husband, and once, with a miraculously fleeting effect which should have +eluded Margery, but did not, at Daniel, eyes blindingly bright in the one flash +that shot from them, but instantly veiled and serene.

+ +

“Now, now, sweet,” said the wool-merchant indulgently, “you know how I shall +hurry back to you.”

+ +

“And how long it will take,” she retorted, pouting. “Three or four nights +solitary. And you’d better bring me something nice to sweeten me for it when +you return.”

+ +

As she knew he would. He never came back from any journey but he brought her +a gift to keep her sweet. He had bought her, but there was enough of cold sense +in him, below his doting, to know that he had to buy her over and over again if +he wanted to keep her. The day he acknowledged it, and examined the +implications, she might well go in fear for her slender throat, for he was an +arrogant and possessive man.

+ +

“You say very truly, madam!” said Margery, stiff-lipped. “I do know, indeed, +how fortunate I am.”

+ +

Only too well! But every man’s fortune, and every woman’s too, can be +changed given a little thought, perseverance and cunning.

+ +

Liliwin had spent his day in so unexpected and pleasant a fashion that for +an hour and more at a time he had forgotten the threat hanging over him. As +soon as High Mass was over, the precentor had hustled him briskly away to the +corner of the cloister where he had already begun to pick apart, with a surgeon’s +delicacy and ruthlessness, the fractured shards of the rebec. Slow, devoted +work that demanded every particle of the pupil’s attention, if he was to assist +at a resurrection. And excellent therapy against the very idea of death.

+ +

“We shall put together what is here broken,” said Brother Anselm, intent and +happy, “for an avowal on our part. No matter if the product, when achieved, +turns out to be flawed, yet it shall speak again. If it speaks with a +stammering voice, then we shall make another, as one generation follows its +progenitor and takes up the former music. There is no absolute loss. Hand me +here that sheet of vellum, son, and mark in what order I lay these fragments +down.” Mere splinters, a few of them, but he set them carefully in the shape +they should take when restored. “Do you believe you will play again upon this +instrument?”

+ +

“Yes,” said Liliwin, fascinated, “I do believe.”

+ +

“That’s well, for faith is necessary. Without faith nothing is +accomplished.” He mentioned this rare tool as he would have mentioned any other +among those laid out to his hand. He set aside the fretted bridge. “Good workmanship, +and old. This rebec had more than one master before it came to you. It will not +take kindly to silence.”

+ +

Neither did he. His brisk, gentle voice flowed like a placid stream while he +worked, and its music lulled like the purling of water. And when he had picked +apart and set out in order all the fragments of the rebec, and placed the +vellum that held them in a safe corner, covered with a linen cloth, to await +full light next day, he confronted Liliwin at once with his own small portative +organ, and demanded he should try his hand with that. He had no need to +demonstrate its use, Liliwin had seen one played, but never yet had the chance +to test it out for himself.

+ +

He essayed the fingering nimbly enough at his first attempt, but +concentrated so totally on the tune he was playing that he forgot to work the +little bellows with his left hand, and the air ran out with a sigh into +silence. He caught himself up with a startled laugh, and tried again, too +vigorously, his playing hand slow on the keys. At the third try he had it. He +played with it, entranced, picked out air after air, getting the feel of it, +balancing hand against hand, growing ambitious, attempting embellishments. Five +fingers can do only so much.

+ +

Brother Anselm presented to him a curious, figured array of signs upon +vellum, matched by written symbols which he knew to be words. He could not read +them, since he could not read in any tongue. To him this meant nothing more +than a pleasing pattern, such as a woman might draw for her embroidery.

+ +

“You never learned this mystery? Yet I think you would pick it up readily. +This is music, set down so that the eye, no less than the ear, may master it. +See here, this line of neums here! Give me the organ.”

+ +

He took it and played a long line of melody. “That—what you have heard—that +is written down here. Listen again!” And again he plucked it jubilantly forth. +“There, now sing me that!”

+ +

Liliwin flung up his head and paid him back the phrase.

+ +

“Now, follow me still… answer as I go.”

+ +

It was an intoxication, line after line of music to copy and toss back. +Within minutes Liliwin had begun to embellish, to vary, to return a higher echo +that chorded with the original.

+ +

“I could make of you a singer,” said Brother Anselm, sitting back in high +content.

+ +

“I am a singer,” said Liliwin. He had never before understood fully +how proud he was of being able to say so.

+ +

“I do believe it. Your music and mine go different ways, but both of them +are made up of these same small signs here, and the sounds they stand for. If +you stay a little, I shall teach you how to read them,” promised Anselm, +pleased with his pupil. “Now, take this, practise some song of your own with +it, and then sing it to me.”

+ +

Liliwin reviewed his songs, and was somewhat abashed to discover how many of +them must be suppressed here as lewd and offensive. But not all were so. He had +a favourite, concerned with the first revelation of young love, and recalling +it now, he recalled Rannilt, as poor as himself, as unconsidered, in her smoky +kitchen and coarse gown, with her cloud of black hair and pale, oval face lit +by radiant eyes. He fingered out the tune, feeling his way, his left hand now +deft and certain on the bellows. He played and sang it, and grew so intent upon +the singing that he scarcely noticed how busily Brother Anselm was penning +signs upon his parchment.

+ +

“Will you believe,” said Anselm, delightedly proffering the leaf, “that what +you have just sung to me is written down here? Ah, not the words, but the air. +This I will explain to you hereafter, you shall learn both how to inscribe and +how to decypher. That’s a very pleasant tune you have there. It could be used +for the ground of a Mass. Well, now, that’s enough for now, I must go and +prepare for Vespers. Let be until tomorrow.”

+ +

Liliwin set the organetto tenderly back on its shelf, and went out, dazed, +into the early evening. A limpid, pale-blue day was drifting away into a deeper +blue twilight. He felt drained and gentle and fulfilled, like the day itself, +silently and hopefully alive. He thought of his battered wooden juggling rings +and balls, tucked away under his folded brychans in the church porch. They +represented another of his skills, which, if not practised, would rust and be +damaged. He was so far buoyed up by his day that he went to fetch them, and +carried them away hopefully into the garden, which opened out level below level +to the pease-fields that ran down to the Meole brook. There was no one there at +this hour, work was over for the day. He untied the cloth, took out the six +wooden balls and the rings after them, and began to spin them from hand to +hand, testing his wrists and the quickness of his eye.

+ +

He was still stiff from bruises and fumbled at first, but after a while the +old ease began to return to him, and his pleasure in accomplishment. This might +be a very humble skill, but it was still an achievement, and his, and he +cherished it. Encouraged, he put the balls and rings away, and began to try out +the suppleness of his thin, wiry body, twisting himself into grotesque knots. +That cost him some pain from muscles trampled and beaten, but he persisted, +determined not to give up. Finally he turned cartwheels all along the headland +across the top of the pease-fields, coiled himself into a ring and rolled down +the slope to the banks of the brook, and made his way up again, the slope being +gentle enough, in a series of somersaults.

+ +

Arrived again at the level where the vegetable gardens and the enclosed herbarium +began, he uncurled himself, flushed and pleased, to find himself gazing up at a +couple of yards distance into the scandalised countenance of a sour-faced +brother almost as meagre as himself. He stared, abashed, into eyes rounded and +ferocious with outrage.

+ +

“Is this how you reverence this holy enclave?” demanded Brother Jerome, +genuinely incensed. “Is such foolery and lightmindedness fit for our abbey? And +have you, fellow, so little gratitude for the shelter afforded you here? You do +not deserve sanctuary, if you value it so lightly. How dared you so affront +God’s enclosure?”

+ +

Liliwin shrank and stammered, out of breath and abased to the ground. “I +meant no offence. I am grateful, I do hold the abbey in reverence. I only +wanted to see if I could still master my craft. It is my living, I must +practise it! Pardon if I’ve done wrong!” He was easily intimidated, here where +he was in debt, and in doubt how to comport himself in a strange world. All his +brief gaiety, all the pleasure of the music, ebbed out of him. He got to his +feet almost clumsily, who had been so lissome only moments ago, and stood +trembling, shoulders bowed and eyes lowered.

+ +

Brother Jerome, who seldom had business in the gardens, being the prior’s +clerk and having no taste for manual labour, had heard from the great court the +small sound, strange in these precincts, of wooden balls clicking together in +mid-air, and had come to investigate in relative innocence. But once in view of +the performance, and himself screened by bushes fringing Brother Cadfael’s +herb-garden, he had not called a halt at once and warned the offender of his +offence, but remained in hiding, storing up a cumulative fund of indignation +until the culprit uncoiled at his feet. It may be that a degree of guilt on his +own part rendered more extreme the reproaches he loosed upon the tumbler.

+ +

“Your living,” he said mercilessly, “ought to engage you rather in +prayers and self-searchings than in these follies. A man who has such charges +hanging over him as you have must concern himself first with his soul’s +welfare, for whether he has a living to make hereafter or none, he has a soul +to save when his debt in this world is paid. Think on that, and go put your +trumpery away, as long as you are sheltered here. It is not fitting! It is +blasphemy! Have you not enough already unpaid on your account?”

+ +

Liliwin felt the terror of the outer world close in on him: it could not be +long evaded. As some within here wore hovering haloes, so he wore a noose, +invisible but ever-present.

+ +

“I meant no harm,” he whispered hopelessly and turned, half-blind with +misery, to grope for his poor bundle of toys and blunder hastily away.

+ +

“Tumbling and juggling, there in our gardens,” Jerome reported, still +burning with offence, “like a vagabond player at a fair. How can it be excused? +Sanctuary is lawful for those who come in proper deference, but this… I +reproved him, of course. I told him he should be thinking rather of his eternal +part, having so mortal a charge against him. ‘My living,’ he says! And he with a +life owing!”

+ +

Prior Robert looked down his patrician nose, and maintained the fastidious +and grieved calm of his noble countenance. “Father Abbot is right to observe +the sanctity of sanctuary, it may not be discarded. We are not to blame, and +need not be concerned, for the guilt or innocence of those who lay claim to it. +But we are, indeed, concerned for the good order and good name of our house, +and I grant you this present guest is little honour to us. I should be happier +if he took himself off and submitted himself to the law, that is true. But +unless he does so, we must bear with him. To reprove where he offends is not +only our due, but our duty. To use any effort to influence or eject him is far +beyond either. Unless he leaves of his own will,” said Prior Robert, “both you +and I, Brother Jerome, must succour, shelter and pray for him.”

+ +

How sincerely, how resolutely. But how reluctantly!

+
+
+

Chapter Five

+ +

« ^ »

+ +

Monday: from dawn to Compline

+ +

Sunday passed, +clear and fine, and Monday came up no less sunnily, a splendid washing day, +with a warm air and a light breeze, and bushes and turf dry and springy. The +Aurifaber household was always up and active early on washing days, which were +saved up two or three weeks at a time, to make but one upheaval of the heating +of so much water, and such labour of scrubbing and knuckling with ash and lye. +Rannilt was up first, to kindle the fire under the brick and clay boiler and +hump the water from the well. She was stronger than she looked and used to the +weight. What burdened her far more, and to that she was not used, was the +terror she felt for Liliwin.

+ +

It was with her every moment. If she slept, she dreamed of him, and awoke +sweating with fear that he might be hunted out already and taken and she none +the wiser. And while she was awake and working, his image was ever in her mind, +and a great stone of anxiety hot and heavy in her breast. Fear for yourself +crushes and compresses you from without, but fear for another is a monster, a +ravenous rat gnawing within, eating out your heart.

+ +

What they said of him was false, could not under any circumstances be true. +And it was his life at stake! She could not help hearing all that was said of +him among them, how they all united to accuse him, and promised themselves he +should hang for what he had done. What she was certain in her heart and soul he +had not done! It was not in him to strike down any man, or rob any +man’s coffers.

+ +

The locksmith, up early for him, heard her drawing up the bucket from the +well, and came out from his back door to stroll down into the garden in the +sunlight and pass the time of day. Rannilt did not think he would have troubled +if he had known it was only the maidservant. He made a point of being attentive +to his landlord’s family, and never missed the common neighbourly courtesies, +but his notice seldom extended to Rannilt. Nor did he linger on this fine +morning, but took a short turn about the yard and returned to his own door. +There he looked back, eyeing for a moment the obvious preparations at the +goldsmith’s house, the great mound of washing in hand, and the normal bustle +just beginning.

+ +

Susanna came down with her arms full of linen, and went to work with her +usual brisk, silent competence. Daniel ate his breakfast and went to his +workshop, leaving Margery solitary and irresolute in the hall. Too much had +happened on her wedding night, she had had no time to grow used to house and +household, or consider her own place in it. Wherever she turned to make herself +useful, Susanna had been before her. Walter lay late, nursing his sore head, +and Dame Juliana kept her own chamber, but Margery was too late to carry food +and drink to either, it was already done. There was no need yet to think of +cooking, and in any case all the household keys were on Susanna’s girdle. +Margery turned her attention to the one place where she felt herself and her +own wishes to be dominant, and set to work to rearrange Daniel’s bachelor chamber +to her own taste, and clear out the chest and press which must now make room +for her own clothes and stores of linen. In the process she discovered much +evidence of Dame Juliana’s noted parsimony. There were garments which must have +belonged to Daniel as a growing boy, and could certainly never again be worn by +him. Neatly mended again and again, they had all been made to last as long as +possible, and even when finally outgrown, had still been folded away and kept. +Well, she was now Daniel’s wife, she would have this chamber as she wanted it, +and be rid of these useless and miserly reminders of the past. Today the +household might still be running on its customary wheels, as though she had no +part to play, but it would not always be so. She was in no haste, she had a +great deal of thinking to do before she took action.

+ +

On her knees in the yard, Rannilt scrubbed and pummelled, her hands sore +from the lye. By mid-morning the last of the washing was wrung and folded and +piled into a great wicker basket. Susanna hoisted it on her hip and bore it +away down the slope of the garden, and through the deep arch in the town wall, +to spread it out on the bushes and the smooth plane of grass that faced almost +due south to the sun. Rannilt cleared away the tub and mopped the floor, and +went in to tend the fire and set the salt beef simmering for dinner.

+ +

Here quiet and alone, she was suddenly so full of her pain on Liliwin’s +account that her eyes spilled abrupt tears into the pot, and once the flow +began she could not dam it. She groped blindly about the kitchen, working by +touch, and shedding helpless tears for the first man who had caught her fancy, +and the first who had ever fancied her.

+ +

Absorbed into her misery, she did not hear Susanna come quietly into the +doorway behind her, and halt there at gaze, watching the fumbling hands feeling +their way, and the half-blind eyes still streaming.

+ +

“In God’s name, girl, what is it with you now?”

+ +

Rannilt started and turned guiltily, stammering that it was nothing, that +she was sorry, that she was getting on with her work, but Susanna cut her off +sharply:

+ +

“It is not nothing! I’m sick of seeing you thus moping and useless. You’ve +been limp as a sick kitten this two days past, and I know why. You have that +miserable little thief on your mind—I know! I know he wound about you with his +soft voice and his creeping ways, I’ve watched you. Must you be fool enough to +fret over a guilty wretch the like of that?”

+ +

She was not angry; she was never angry. She sounded impatient, even +exasperated, but still contemptuously kind, and her voice was level and +controlled as ever. Rannilt swallowed the choking residue of tears, shook the +mist from her eyes, and began to be very busy with her pots and pans, looking +hurriedly about her for a distraction which would turn attention from herself +at any cost. “It came over me just for a minute: I’m past it now. Why, you’ve +got your feet and the hem of your gown wet,” she exclaimed, seizing gratefully +on the first thing that offered. “You should change your shoes.”

+ +

Susanna shrugged the diversion scornfully aside. “Never mind my wet feet. +The river’s up a little, I was not noticing until I went too near the edge, +leaning to hang a shirt on the bushes. What of your wet eyes? That’s more to +the point. Oh, fool girl, you’re wasting your fancy! This is a common rogue of +the roads, with many a smaller deed of the kind behind him, and he’ll get +nothing but his due in the noose that’s waiting for him. Get sense, and put him +out of your mind.”

+ +

“He is not a rogue,” said Rannilt, despairingly brave. “He did not do it, I +know it, I know him, he could not. It isn’t in him to do violence. And +I do fret for him, I can’t help it.”

+ +

“So I see,” said Susanna resignedly. “So I’ve seen ever since they ran him +to ground. I tire of him and of you. I want you in your wits again. God’s +truth, must I carry this household on my back without even your small help?” +She gnawed a thoughtful lip, and demanded abruptly: “Will it cure you if I let +you go see for yourself that the tumbler is alive and whole, and out of our +reach for a while, more’s the pity? Yes, and likely to worm his way out of even +this tangle in the end!”

+ +

She had spoken magical words. Rannilt was staring up at her dry-eyed, bright +as a candle-flame. “See? See him? You mean I could go there?”

+ +

“You have legs,” said Susanna tartly. “It’s no distance. They don’t close +their gates against anyone. You may even come back in your right senses, when +you see how little store he sets by you, while you’re breaking your +fool heart for him. You may get to know him for what he is, and the better for +you. Yes, go. Go, and be done with it! This once I’ll manage without you. Let +Daniel’s wife start making herself useful. Good practice for her.”

+ +

“You mean it?” whispered Rannilt, stricken by such generosity. “I may go? +But who will see to the broth here, and the meat?”

+ +

“I will. I have often enough, God knows! I tell you, go, go quickly, before +I change my mind, stay away all day long, if that will send you back cured. I +can very well do without you this once. But wash your face, girl, and comb your +hair, and do yourself and us credit. You can take some of those oat-cakes in a +basket, if you wish, and whatever scraps were left from yesterday. If he felled +my father,” said Susanna roughly, turning away to pick up the ladle and stir +the pot simmering on the hob, “there’s worse waiting for him in the end, no +need to grudge him a mouthful while he is man alive.” She looked back over a +straight shoulder at Rannilt, who still hovered in a daze. “Go and visit your +minstrel, I mean it, you have leave. I doubt if he even remembers your face! Go +and learn sense.”

+ +

Lost in wonder, and only half believing in such mercies, Rannilt washed her +face and tidied her tangle of dark hair with trembling hands, seized a basket +and filled it with whatever morsels were brusquely shoved her way, and went out +through the hall like a child walking in its sleep. It was wholly by chance +that Margery was coming down the stairs, with a pile of discarded garments on +her arm. She marked the small, furtive figure flitting past below, and in +surprised goodwill, since this waif was alien and lonely here as she was, +asked: “Where are you sent off to in such a hurry, child?”

+ +

Rannilt halted submissively, and looked up into Margery’s rounded, fresh countenance. +“Mistress Susanna gave me leave. I’m going to the abbey, to take this provision +to Liliwin.” The name, so profoundly significant to her, meant nothing to +Margery. “The minstrel. The one they say struck down Master Walter. But I’m +sure he did not! She said I may go, see for myself how he’s faring—because I +was crying…”

+ +

“I remember him,” said Margery. “A little man, very young. They’re sure he’s +the guilty one, and you are sure he is not?” Her blue eyes were demure. She +hunted through the pile of garments on her arm, and very faintly and fleetingly +she smiled. “He was not too well clothed, I recall. There is a cotte here that +was my husband’s some years ago, and a capuchon. The little man could wear +them, I think. Take them with you. It would be a pity to waste them. And +charity is approved of in Heaven, even to sinners.”

+ +

She sorted them out gravely, a good dark-blue coat outgrown while it was +still barely patched, and a much-mended caped hood in russet brown. “Take them! +They’re of no use here.” None, except for the satisfaction it gave her to +despatch them to the insignificant soul condemned by every member of her new +family. It was her gesture of independence.

+ +

Rannilt, every moment more dazed, took the offerings and tucked them into +her basket, made a mute reverence, and fled before this unprecedented and +hardly credible vein of good will should run out, and food, clothing, holiday +and all fall to ruin round her.

+ +

Susanna cooked, served, scoured and went about her circumscribed realm with +a somewhat grim smile on her lips. The provisioning of the house under her +governance was discreetly more generous than ever it had been under Dame +Juliana, and on this day there was enough and to spare, even after she had +carried his usual portion to Iestyn in the workshop, and sat with him for +company while he ate, to bring back the dish to the kitchen afterwards. What +remained was not worth keeping to use up another day, but there was enough for +one. She shredded the remains of the boiled salt beef into it, and took it +across to the locksmith’s shop, as she had sometimes done before when there was +plenty.

+ +

John Boneth was at work at his bench, and looked up as she entered, bowl in +hand. She looked about her, and saw everything in placid order, but no sign of +Baldwin Peche, or the boy Griffin, probably out on some errand.

+ +

“We have a surfeit, and I know your master’s no great cook. I brought him +his dinner, if he hasn’t eaten already.”

+ +

John had come civilly to his feet, with a deferential smile for her. They +had known each other five years, but always at this same discreet distance. The +landlord’s daughter, the rich master-craftsman’s girl, was no meat for a mere +journeyman.

+ +

“That’s kind, mistress, but the master’s not here. I’ve not seen him since +the middle of the morning, he’s left me two or three keys to cut. I fancy he’s +off for the day. He said something about the fish rising.”

+ +

There was nothing strange in that. Baldwin Peche relied on his man to take +charge of the business every bit as competently as he could have done himself, +and was prone to taking holidays whenever it suited his pleasure. He might be +merely making the round of the ale-houses to barter his own news for whatever +fresh scandal was being whispered, or he might be at the butts by the +riverside, betting on a good marksman, or out in his boat, which he kept in a +yard near the Watergate, only a few minutes down-river. The young salmon must +be coming up the Severn by this time. A fisherman might well be tempted out to +try his luck.

+ +

“And you don’t know if he’ll be back?” Susanna read his face, shrugged and +smiled. “I know! Well, if he’s not here to eat it… I daresay you have still +room to put this away, John?” He brought with him, usually, a hunk of bread and +a strip of salt bacon or a piece of cheese, meat was festival fare in his +mother’s house. Susanna set down her bowl before him on the bench, and sat down +on the customer’s stool opposite, spreading her elbows comfortably along the +boards. “It’s his loss. In an ale-house he’ll pay more for poorer fare. I’ll +sit with you, John, and take back the bowl.”

+ +

Rannilt came down the Wyle to the open gate of the town, and passed through +its shadowed arch to the glitter of sunlight on the bridge. She had fled in +haste from the house, for fear of being called back, but she had lingered on +the way through the town for fear of what lay before her. For the course was +fearful, to one unschooled, half-wild, rejected by Wales and never welcomed in England +but as a pair of labouring hands. She knew nothing of monks or monasteries, and +none too much even of Christianity. But there inside the abbey was Liliwin, and +thither she would go. The gates, Susanna had said, were never closed against +any.

+ +

On the far side of the bridge she passed close by the copse where Liliwin +had curled up to sleep, and been hunted out at midnight. On the other side of +the Foregate lay the mill pool, and the houses in the abbey’s grant, and +beyond, the wall of the enclave began, and the roofs of infirmary and school +and guest-hall within, and the tall bulk of the gatehouse. The great west door +of the church, outside the gates, confronted her in majesty. But once timidly +entering the great court, she found reassurance. Even at this hour, perhaps the +quietest of the day, there was a considerable bustle of coming and going within +there, guests arriving and departing, servants ambling about on casual errands, +petitioners begging, packmen taking a midday rest, a whole small world of +people, some of them as humble as herself. She could walk in there among them, +and never be noticed. But still she had to find Liliwin, and she cast about her +for the most sympathetic source of information.

+ +

She was not blessed in her choice. A small man, in the habit of the house, +scurrying across the court; she chose him because he was as small and slight as +Liliwin, and his shoulders had a discouraged droop which reminded her of +Liliwin, and because someone who looked so modest and disregarded must surely +feel for others as insignificant as himself. Brother Jerome would have been +deeply offended if he had known. As it was, he was not displeased at the low +reverence this suppliant girl made to him, and the shy whisper in which she +addressed him.

+ +

“Please, sir, I am sent by my lady with alms for the young man who is here +in sanctuary. If you would kindly teach me where I may find him.”

+ +

She had not spoken his name because it was a private thing, to be kept +jealously apart. Jerome, however he might regret that any lady should be so +misguided as to send alms to the offender, was somewhat disarmed by the +approach. A maid on an errand was not to be blamed for her mistress’s errors.

+ +

“You will find him there, in the cloister, with Brother Anselm.” He +indicated the direction grudgingly, disapproving of Brother Anselm’s complacent +usage with an accused man, but not censuring Rannilt, until he noted the +brightening of her face and the lightness of her foot as she sprang to follow +where he pointed. Not merely an errand-girl, far too blithe! “Take heed, child, +what message you have to him must be done decorously. He is on probation of a +most grave charge. You may have half an hour with him, you may and you should +exhort him to consider on his soul. Do your errand and go!”

+ +

She looked back at him with great eyes, and was very still for one instant +in her flight. She faltered some words of submission, while her eyes flamed +unreadably, with a most disquieting brilliance. She made a further deep +reverence, to the very ground, but sprang from it like an angel soaring, and +flew to the cloister whither he had pointed her.

+ +

It seemed vast to her, four-sided in stony corridors about an open garden, +where spring flowers burst out in gold and white and purple on a grassy ground. +She flitted the length of one walk between terror and delight, turned along the +second in awe of the alcove cells furnished with slanted tables and benches, +empty but for one absorbed scholar copying wonders, who never lifted his head +as she passed by. At the end of this walk, echoing from such another cell, she +heard music. She had never before heard an organ played, it was a magical sound +to her, until she heard a sweet, lofty voice soar happily with it, and knew it +for Liliwin’s.

+ +

He was bending over the instrument, and did not hear her come. Neither did +Brother Anselm, equally absorbed in fitting together the fragments of the +rebec’s back. She stood timidly in the opening of the carrel, and only when the +song ended did she venture speech. At this vital moment she did not know what +her welcome would be. What proof had she that he had thought of her, since that +hour they had spent together, as she had thought ceaselessly of him? It might +well be that she was fooling herself, as Susanna had said.

+ +

“If you please…” began Rannilt humbly and hesitantly.

+ +

Then they both looked up. The old man viewed her with mildly curious eyes, +unastonished and benign. The young one stared, gaped and blazed, in incredulous +joy, set aside his strange instrument of music blindly on the bench beside him, +and came to his feet slowly, warily, all his movements soft almost to stealth, +as though any sudden start might cause her to quiver and dissolve into light, +vanishing like morning mist.

+ +

“Rannilt… It was you?”

+ +

If this was indeed foolery, then she was not the only fool. She looked +rather at Brother Anselm, whose devoted fingers were held poised, not to divert +by the least degree the touch he had suspended on his delicate operations.

+ +

“If you please, I should like to speak with Liliwin. I have brought him some +gifts.”

+ +

“By all means,” said Brother Anselm amiably. “You hear, boy? You have a +visitor. There, go along and be glad of her. I shall not need you now for some +hours. I’ll hear your lesson later.”

+ +

They moved towards each other in a dream, wordless, took hands and stole +away.

+ +

“I swear to you, Rannilt, I never struck him, I never stole from him, I +never did him wrong.” He had said it at least a dozen times, here in the +shadowy porch where his brychans were folded up, and his thin pallet spread, +and the poor tools of his craft hidden away in a corner of the stone bench as though +some shame attached to them. And there had never been any need to say it even +once, as she a dozen times had answered him.

+ +

“I know, I know! I never believed for a moment. How could you doubt it? I +know you are good. They will find it out, they will have to own it.”

+ +

They trembled together and kept fast hold of hands in a desperate clasp, and +the touch set their unpractised bodies quivering in an excitement neither of +them understood.

+ +

“Oh, Rannilt, if you knew! That was the worst of all, that you might shrink +from me and believe me so vile… They believe it, all of them. Only +you…”

+ +

“No,” she said stoutly, “I’m not so sure. The brother who comes to physic +Dame Juliana, the one who brought back your things… And that kind brother who +is teaching you… Oh, no, you are not abandoned. You must not think it!”

+ +

“No!” he owned thankfully. “Now I do believe, I do trust, if you +are with me…” He was lost in wonder that anyone in that hostile household +should send her to him. “She was good, your lady! I’m so beholden to her…”

+ +

Not for the gifts of food, orts to her, delicacies to him. No, but for this +nearness that clouded his senses in a fevered warmth and delight and disquiet +he had never before experienced, and which could only be love, the love he had +sung by rote for years, while his body and mind were quite without +understanding.

+ +

Brother Jerome, true to what he felt to be his duty, had marked the passing +of time, and loomed behind them, approaching inexorably along the walk from the +great court. His sandals silent on the flagstones, he observed as he came the +shoulders pressed close, the two heads, the flaxen and the black, inclined +together with temples almost touching. Certainly it was time to part them, this +was no place for such embraces.

+ +

“It will all be well in the end,” said Rannilt, whispering. “You’ll see! +Mistress Susanna—she says as they say, and yet she let me come. I think she +doesn’t really believe… She said I might stay away all day long…”

+ +

“Oh, Rannilt… Oh, Rannilt, I do so love you…”

+ +

“Maiden,” said Brother Jerome, harshly censorious behind them, “you have had +time enough to discharge your mistress’s errand. There can be no further stay. +You must take your basket and depart.”

+ +

A shadow no bigger than Liliwin’s, there behind them black against the +slanting sun of mid-afternoon, and yet he cast such a darkness over them as +they could hardly bear. They had only just linked hands, barely realised the +possibilities that lie within such slender bodies, and they must be torn apart. +The monk had authority, he spoke for the abbey, and there was no denying him. +Liliwin had been granted shelter, how could he then resist the restrictions +laid upon him?

+ +

They rose, tremulous. Her hand in his clung convulsively, and her touch ran +through him like a stiffening fire, drawn by a great, upward wind that was his +own desperation and anger.

+ +

“She is going,” said Liliwin. “Only give us, for pity’s sake, some moments +in the church together for prayer.”

+ +

Brother Jerome found that becoming, even disarming, and stood back from them +as Liliwin drew her with him, the basket in his free hand, in through the porch +to the dark interior of the church. Silence and dimness closed on them. Brother +Jerome had respected their privacy and remained without, though he would not go +far until he saw one of them emerge alone.

+ +

And it might be the last time he would ever see her! He could not bear it +that she should go so soon, perhaps to be lost for ever, when she had leave to +be absent all day long. He closed his hand possessively on her arm, drawing her +deep into the shadowy, stony recesses of the transept chapel beyond the parish +altar. She should not go like this! They were not followed, there was no one +else here within at this moment, and Liliwin was well acquainted now with every +corner and cranny of this church, having prowled it restlessly and fearfully on +his first night here alone, when his ears were still pricked for sounds of +pursuit, and he was afraid to sleep on his pallet in the porch.

+ +

“Don’t go, don’t go!” His arms were clasped tightly about her as they +pressed together into the darkest corner, and his lips were whispering +agitatedly against her cheek. “Stay with me! You can, you can, I’ll show you a +place… No one will know, no one will find us.”

+ +

The chapel was narrow, the altar wide, all but filling the space between its +containing columns, and stood out somewhat from the niche that tapered behind +it. There was a little cavern there, into which only creatures as small and +thin as they could creep. Liliwin had marked it down as a place to which he +might retreat if the hunters broke in, and he knew his own body could negotiate +the passage, so for her it would be no barrier. And within there was darkness, +privacy, invisibility.

+ +

“Here, slip in here! No one will see. When he’s satisfied, when he goes +away, I’ll come to you. We can be together until Vespers.”

+ +

Rannilt went where he urged her; she would have done anything he asked, her +hunger was as desperate as his. The empty basket was drawn through the narrow +space after her. Her wild whisper breathed back from the darkness: “You will +come? Soon?”

+ +

“I’ll come! Wait for me…”

+ +

Invisible and still, she made no murmur nor rustle. Liliwin turned, +trembling, and went back past the parish altar, and out at the south porch into +the east walk of the cloisters. Brother Jerome had had the grace to withdraw +into the garth, to keep his jealous watch a little less blatantly, but his +sharp eyes were still on the doorway, and the emergence of the solitary figure, +head drooping and shoulders despondent, appeared to satisfy him. Liliwin did +not have to feign dejection, he was already in tears of excitement, compounded +of joy and grief together. He did not turn along the scriptorium to go back to +Brother Anselm, but went straight past the bench in the porch, where the gifts of +food and clothing lay on his folded brychans, and out into the court and the +garden beyond. But not far, only into cover among the first bushes, where he +could look back and see Brother Jerome give over his vigil, and depart briskly +in the direction of the grange court. The girl was gone, from the west door of +the church; the disturbing presence was removed, monastic order restored, and +Brother Jerome’s authority had been properly respected.

+ +

Liliwin flew back to his pallet in the porch, rolled up food and clothing in +his blankets, and looked round carefully to make sure there was now no one +paying any attention to him, either within or without the church. When he was +certain, he slipped in with his bundle under his arm, darted into the chapel, +and slid as nimbly as an eel between altar and pillar into the dark haven +behind. Rannilt’s hands reached out for him, her cheek was pressed against his, +they shook together, almost invisible even to each other, and by that very +mystery suddenly loosed from all the restraints of the outer world, able to +speak without speech, delivered from shyness and shame, avowed lovers. This was +something quite different even from sitting together in the porch, before +Jerome’s serpent hissed into their Eden. There they had never got beyond +clasping hands, and even those clasped hands hidden between them, as if a +matter for modesty and shame. Here there was neither, only a vindicated candour +that expanded in darkness, giving and receiving passionate, inexpert caresses.

+ +

There was room there to make a nest, with the blankets and the basket and +Daniel’s outgrown clothes, and if the stone floor was thick with a generation +or more of soft, fine dust, that only helped to cushion the couch they laid +down for themselves. They sat huddled together with their backs against the +stone wall, sharing their warmth, and the morsels Susanna had discarded, and +holding fast to each other for reassurance, until they drifted into a +dream-like illusion of safety where reassurance was unnecessary.

+ +

They talked, but in few and whispered words.

+ +

“Are you cold?”

+ +

“No.”

+ +

“Yes, you’re trembling.” He shifted and drew her into his arm, close against +his breast, and with his free hand plucked up a corner of the blanket over her +shoulder, binding her to him. She stretched up her arm within the rough wool, +slipped her hand about his neck, and embraced him with lips and cheek and +nestling forehead, drawing him down with her until they lay breast to breast, +heaving as one to great, deep-drawn sighs.

+ +

There was some manner of lightning-stroke, as it seemed, that convulsed them +both, and fused them into one without any coherent action on their part. They +were equally innocent, equally knowing. Knowing by rote is one thing. What they +experienced bore no resemblance to what they had thought they knew. Afterwards, +shifting a little only to entwine more closely and warmly, they fell asleep in +each other’s arms, to quicken an hour or more later to the same compulsion, and +love again without ever fully awaking. Then they slept again, so deeply, in +such an exhaustion of wonder and fulfilment, that even the chanting of Vespers +in the choir did not disturb them.

+ +

“Shall I fetch in the linen for you?” Margery offered in the afternoon, +making a conciliatory foray into Susanna’s domain, and finding that composed +housekeeper busy with preparations for the evening’s supper.

+ +

“Thank you,” said Susanna, hardly looking up from her work, “but I’ll do +that myself.” Not one step is she going to advance towards me, thought Margery, +damped. Her linen, her stores, her kitchen! And at +that Susanna did look up, even smiled; her usual, wry smile, but not +unfriendly. “If you wish me well, do take charge of my grandmother. You are new +to her, she’ll take more kindly to you, and be more biddable. I have had this some +years, she and I wear out each other. We are too like. You come fresh. It would +be a kindness.”

+ +

Margery was silenced and disarmed. “I will,” she said heartily, and went +away to do her best with the old woman, who, true enough, undoubtedly curbed +her malevolence with the newcomer.

+ +

Only later in the evening, viewing Daniel across the trestle table, mute, +inattentive and smugly glowing with some private satisfaction, did she return +to brooding on her lack of status here, and reflecting at whose girdle the keys +were hung, and whose voice bound or loosed the maidservant who was still +absent.

+ +

“I marvel,” said Brother Anselm, coming out from the refectory after supper, +“where my pupil can have got to. He’s been so eager, since I showed him the +written notes. An angel’s ear, true as a bird, and a voice the same. And he has +not even been to the kitchen for his supper.”

+ +

“Nor come to have his arm dressed,” agreed Brother Cadfael, who had spent +the whole afternoon busily planting, brewing and compounding in his herbarium. +“Though Oswin did look at it earlier, and found it healing very well.”

+ +

“There was a maidservant here bringing him a basket of dainties from her +mistress’s table,” said Jerome, one ear pricked in their direction. “No doubt +he felt no appetite for our simple fare. I had occasion to admonish them. He +may have taken some grief, and be moping solitary.”

+ +

It had not occurred to him, until then, that he had not seen the unwanted +guest since the boy had come out of the church alone; now it seemed, moreover, +that Brother Anselm, who had had more reason to expect to spend time with his +pupil, had not seen hide or hair of him, either. The abbey enclave was +extensive, but not so great that a man virtually a prisoner should disappear in +it. If, that is, he was still within it?

+ +

Jerome said no word more to his fellows, but spent the final half-hour +before Compline making a rapid search of every part of the enclave, and ended +at the south porch. The pallet on the stone bench was bare and unpressed, the +brychans unaccountably missing. He did not notice the small cloth bundle tucked +under a corner of the straw. As far as he could see, there was no sign left of +Liliwin’s presence.

+ +

He reported as much to Prior Robert, returning breathless just before +Compline was due to begin. Robert did not exactly smile, his ascetic face +remained benign and bland as ever, but he did somehow radiate an air of relief +and cautious pleasure.

+ +

“Well, well!” said Robert. “If the misguided youth has been so foolish as to +quit his place of safety on account of a woman, it is his own choice. A sad +business, but no blame lights upon any within here. No man can be wise for +another.” And he led the procession into the choir with his usual impressive +gait and saintly visage, and breathed the more easily now that the alien burr +had been dislodged from his skin. He did not warn Jerome to say no word yet to +anyone else within here; there was no need, they understood each other very +well.

+
+
+

Chapter Six

+ +

« ^ »

+ +

Monday night to Tuesday afternoon

+ +

Liliwin awoke +with a jolting shock to darkness, the unmistakable sound of Brother Anselm’s +voice leading the chanting in the choir, a wild sense of fear, and the total +remembrance of the wonderful and terrible thing he and Rannilt had done +together, that revelation of bliss that was at the same time so appalling and +unforgivable a blasphemy. Here, behind the altar, in the presence of relics so +holy, the sin of the flesh, natural and human as it might be out in some meadow +or coppice, became mortal and damning. But the immediate terror was worse than +the distant smell of hellfire. He remembered where he was, and everything that +had passed, and his senses, sharpened by terror and dismay, recognised the +office. Not Vespers! Compline! They had slept for hours. Even the evening was +spent, the night closing in.

+ +

He groped with frantic gentleness along the brychan, to lay a hand over +Rannilt’s lips, and kissed her cheek to awaken her. She started instantly and +fully out of the depths of sleep. He felt her lips move, smiling, against his +palm. She remembered, but not as he did; she felt no guilt and she was not +afraid. Not yet! That was still to come.

+ +

With his lips close to her ear, in the tangle of her black hair, he +breathed: “We’ve slept too long… it’s night, they’re singing Compline.”

+ +

She sat up abruptly, braced and listening with him. She whispered: “Oh +mercy! What have we done? I must go… I shall be so late…”

+ +

“No, not alone… you can’t. All that way in the dark!”

+ +

“I’m not afraid.”

+ +

“But I won’t let you! There are thieves and villains in the night. You +shan’t go alone, I’m coming with you.”

+ +

She put him off from her with a hand flattened against his breast, her +fluttering whisper agitated but still soft on his cheek: “You can’t! You can’t, +you mustn’t leave here, they’re watching outside, they’d take you.”

+ +

“Wait… wait here a moment, let me look.” The faint light from the choir, +shut off by stone walls from their cranny, but feebly reflected into the +chapel, had begun to show in a pallid outline the shape of the altar behind +which they crouched. Liliwin slipped round it, and padded across to peer round +a sheltering column into the nave. There were a number of elderly women of the +Foregate who attended even non-parochial services regularly, having their souls +in mind, their homes only a few paces distant, and nothing more interesting to +do with their evenings in these declining years. Five of them were present on +this fine, mild night, kneeling in the dimness just within Liliwin’s view, and +one of them must have brought a young grandson with her, while another, fragile +enough to need or demand a prop, had a young man in his twenties attendant on +her. Enough of them to provide a measure of cover, if God, or fate, or whatever +held the dice, added the requisite measure of luck.

+ +

Liliwin fled back into the dark chapel, and reached a hand to draw Rannilt +out from their secret nest.

+ +

“Quick, leave the brychans,” he whispered feverishly, “but give me the +clothes—the cotte and capuchon. No one has ever seen me but in these rags…”

+ +

Daniel’s old coat was ample for him, and worn over his own clothes gave him +added bulk, as well as respectability. The nave was lit by only two flares +close to the west door, and the rust-brown capuchon, with its deep +shoulder-cape, widened his build and hid his face to some extent even before he +could hoist it over his head on quitting the church.

+ +

Rannilt clung to his arm, trembling and pleading. “No, don’t… stay here, I’m +afraid for you…”

+ +

“Don’t be afraid! We shall go out with all those people, no one will notice +us.” And whether in terror or no, they would be together still a while longer, +arms linked, hands clasped.

+ +

“But how will you get in again?” she breathed, lips against his cheek.

+ +

“I will. I’ll follow someone else through the gate.” The office was ending, +in a moment the brothers would be moving in procession down the opposite aisle +to the night stairs. “Come, now, close to the people there…”

+ +

The ancient, holy women of the Foregate waited on their knees, faces turned +towards the file of monks as they passed, shadowy, towards their beds. Then +they rose and began their leisurely shuffle towards the west door, and after +them, emerging unquestioned from shadow, went Liliwin and Rannilt, close and +quiet, as though they belonged.

+ +

And it was unbelievably easy. The sheriff’s officers had a guard of two men +constantly outside the gatehouse, where they could cover both the gate itself +and the west door of the church, and they had torches burning, but rather for +their own pleasure and convenience than as a means of noting Liliwin’s +movements, since they had to while away the hours somehow on their watch, and +you cannot play either dice or cards in the dark. By this time they did not believe +that the refugee would make any attempt to leave his shelter, but they knew +their duty and kept their watch faithfully enough. They stood to watch in +silence as the worshippers left the church, but they had no orders to +scrutinise those who went in, and so had not either counted them or observed +them closely, and noted no discrepancy in the numbers leaving. Nor was there +any sign here of the jongleur’s faded and threadbare motley, but neat, plain +burgess clothing. Having no knowledge that a young girl had made her way in, +intent on seeing the accused man, they thought nothing of watching her make her +way out in his company. Two insignificant young people passed and dwindled into +the night on the heels of the old women. What was there in that?

+ +

They were out, they were past, the lights of the torches dimmed behind them, +the cool darkness closed round them, and the hearts that had fluttered up +wildly into their throats, like terrified birds shut into a narrow room, +settled back gradually into their breasts, still beating heavily. By luck two +of the old women, and the young man who supported the elder, inhabited two of +the small houses by the mill, as pensioners of the abbey, and so had to turn +towards the town, and Liliwin and Rannilt did not have to go that way alone +from the gate, or they might have been more conspicuous. When the women had +turned aside to their own doors, and they two alone were stealing silently +between mill-pool on one hand and the copses above the Gaye on the other, and +the stone rise of the bridge showed very faintly before them, Rannilt halted +abruptly, drawing him round face to face with her in the edge of the trees.

+ +

“Don’t come into the town! Don’t! Turn here, to the left, this side the +river, there’s a track goes south, they won’t be watching there. Don’t come +through the gate! And don’t go back! You’re out now, and none of them know. +They won’t, not until tomorrow. Go, go, while you can! You’re free, you can +leave this place…” Her whisper was urgent, resolute with hope for him, desolate +with dismay on her own account. Liliwin heard the one as clearly as the other, +and for a moment he, too, was torn.

+ +

He drew her deeper into the trees, and shut his arms about her fiercely. “No! +I’m coming with you, it isn’t safe for you alone. You don’t know what things +can happen by night in a dark alley. I’ll see you to your own yard. I must, I +will!”

+ +

“But don’t you see…” She beat a small fist against his shoulder in +desperation. “You could go now, escape, put this town behind you. A whole night +to get well away. There’ll be no second chance like this.”

+ +

“And put you behind me, too? And make myself seem what they say I am?” He +put a shaking hand under her chin, and turned up to him none too gently the +face he saw only as a pale oval in the darkness. “Do you want me to +go? Do you want never to see me again? If that’s what you want, say it, and +I’ll go. But say truth! Don’t lie to me!”

+ +

She heaved a huge sigh, and embraced him in passionate silence. In a moment +she breathed: “No! No… I want you safe… But I want you!”

+ +

She wept briefly, while he held her and made soft, inarticulate sounds of +comfort and dismay; and then they went on, for that was settled, and would not +lightly be raised again. Over the bridge, with lambent light flickering up from +the Severn’s dimpling surface on either side, and the torches burning down +redly in the side-pillars of the town gate before them. The watchmen at the +gate were easy, bestirring themselves only when brawlers or obstreperous drunks +rolled in upon them. Two humble but respectable young people hurrying home got +only a glance from them, and an amiable goodnight.

+ +

“You see,” said Liliwin, on their way up the dark slope and curve of the +Wyle, “it was not so hard.” Very softly she said: “No.”

+ +

“I shall go in again just as simply. Late travellers come, I shall tread in +on their heels. If there are none, I can sleep rough over the night, and in +these clothes I can slip in when the morning traffic begins.”

+ +

“You could still go from here,” she said, “when you leave me.”

+ +

“But I will not leave you. When I go from here, you will go with me.”

+ +

He was flying his small pennon of defiance against the wind, and knew it, +but he meant it with all his heart. It might all end ignominiously, he might +still fall like the heron to the fowler, but he had had until now a name, +however humble, never traduced with accusation of theft and violence, and it +was worth a venture to keep that; and now he had a still dearer stake to win or +lose. He would not go. He would abide to win or lose all.

+ +

At the High Cross they turned to the right, and were in narrower and darker +places, and once, at least, something furtive and swift turned aside from their +path, perhaps wary of two, where one might cry out loud enough to rouse others, +even if the second could be laid out with the first blow. Shrewsbury was well +served in its watchmen, but every solitary out at night is at the mercy of +those without scruples, and the watch cannot be everywhere. Rannilt did not +notice. Her fear for Liliwin was not of any immediate danger to him here.

+ +

“Will they be angry with you?” he wondered anxiously, as they drew nearer to +Walter Aurifaber’s shop-front, and the narrow passage through into the yard.

+ +

“She said I might stay all day, if it would cure me.” She smiled invisibly +in the night, far from cured, but armed against any questioning. “She was kind, +I’m not afraid of her, she’ll stand by me.”

+ +

In the deep darkness of a doorway opposite he drew her to him, and she +turned and clung. It came upon them both alike that this might be the last time, +but they clung, and kissed and would not believe it.

+ +

“Now go, go quickly! I shall watch until you’re within.” They stood where he +could gaze deep into the passage, and mark the faint glow from an unshuttered +window within. He put her away from him, turned her about, and gave her a push +to start her on her way. “Run!”

+ +

She was gone, across the street and into the passage, scurrying obediently, +blotting out for a moment the inner glow. Then she was into the yard, and the +small light picked out the shape of her for one instant as she flew past the +hall door and was gone indeed.

+ +

Liliwin stood motionless in the dark doorway, staring after her for a long +time. The night was very still and quiet about him. He did not want to move +away. Even when the dull spark within the yard was quenched, he still stood +there, straining blindly after the way she had gone.

+ +

But he was wrong, the spark had not been quenched, only blotted out from +sight for the minute or so it took for a man’s form to thread the passage +silently and emerge into the street. A tall, well-built man, young by his step, +in a hurry by the way he hurtled out of the passage, and about some private and +nefarious business by the agility and stealth with which he slid in and out of +the deepest shadows as he made off along the lane, with his capuchon drawn well +forward and his head lowered.

+ +

There were but two young men who habited within that burgage at night, and a +man who had played and sung and tumbled a long evening away in their company +had no difficulty in distinguishing between them. In any case, the fine new +coat marked him out, for all his furtive procedure. Only three days married, +where was Daniel Aurifaber off to in such a hurry, late at night?

+ +

Liliwin left his station at last, and went back along the narrow street +towards the High Cross. He saw no more of that flitting figure. Somewhere in +this maze of by-streets Daniel had vanished, about what secret business there +was no knowing. Liliwin made his way down the Wyle to the gate, and was hardly +shaken at being halted by a guard wider awake than his fellows.

+ +

“Well, well, lad, you’re back soon. Wanting out again at this hour? You’re +back and forth like a dog at a fair.”

+ +

“I was seeing my girl safe home,” said Liliwin, truth coming both welcome +and easy. “I’m away back to the abbey now. I’m working there.” And so he was, +and would work the harder the next day for having deserted Brother Anselm on +this one.

+ +

“Oh, you’re in their service, are you?” The guard was benevolent. “Take no +unwary vows, lad, or you’ll lose that girl of yours. Off you go then, and +goodnight to you.”

+ +

The cavern of the gateway, reflecting torchlight from its stony vault, fell +behind him, the arch of the bridge, with liquid silver on either side, opened +before him, and above there was a light veil of cloud pierced here and there by +a stray star. Liliwin crossed, and slipped again into the bushes that fringed +the roadway. The silence was daunting. When he drew nearer to the abbey +gatehouse he was afraid to stir out of cover, and cross the empty street to +brave the scrutiny beyond. Both the west door of the church and the open wicker +of the gate seemed equally inaccessible.

+ +

He stood deep in cover, watching the Foregate, and it came back to him +suddenly and temptingly that he was, indeed, out of sanctuary undetected, and +the whole of the night before him to put as many miles as possible between +himself and Shrewsbury, and hide himself as deeply as possible among men to +whom he was unknown. He was small and weak and fearful, and very greedy for life, +and the ache to escape this overhanging peril was acute. But all the time he +knew he would not go. Therefore he must get back to the one place where for +thirty-seven more days he was safe, here within reach of the house where +Rannilt slaved and waited and prayed for him.

+ +

He had luck in the end, and not even long to wait. One of the lay servants +of the abbey had had his new son christened that day, and opened his house to +the assembly of his relatives and friends to celebrate the occasion. The abbey +stewards, shepherds and herdsmen who had been his guests came back along the +Foregate in a flock, well-fed and merry, to return to their quarters in the +grange court. Liliwin saw them come, spanning the street with their loose-knit +chain, and when they drew near enough, and closed at leisure on the gatehouse, +those bound within taking spacious leave of those living without, so that he +was sure of the destination of perhaps a third of their number, he slipped out +of the bushes and mingled with the fringes of the group. One more in the +dimness made no matter. He went in unquestioned by any, and in the unhurried +dispersal within he slipped away silently into the cloister, and so to his +deserted bed in the south porch.

+ +

He was within the fold, and it was over. He sidled thankfully into the empty +church—a good hour yet before Matins—and went to retrieve his blankets from +behind the altar in the chancel chapel. He was very tired, but so agonisingly +awake that sleep seemed very far off. Yet when he had spread his bedding again +on his pallet, tucked away under the straw his new capuchon and cotte, and +stretched himself out, still trembling, along the broad stone bench, sleep came +on him so abruptly that all he knew of it was the descent, fathoms deep, into a +well of darkness and peace.

+ +

Brother Cadfael rose well before Prime to go to his workshop, where he had +left a batch of troches drying overnight. The bushes in the garden, the herbs +in the enclosed herbarium, all glimmered softly with the lingering dew of a +brief shower, and reflected back the dawn sunlight from thousands of tiny +facets of silver. Another fine, fresh day beginning. Excellent for planting, +moist, mild, the soil finely crumbled after the intense frosts of the hard +winter. There could be no better auguries for germination and growth.

+ +

He heard the bell rousing the dortoir for Prime, and went directly to the +church as soon as he had put his troches safely away. And there in the porch +was Liliwin, his bedding already folded tidily away, his ill-cobbled motley exchanged +for his new blue cotte, and his pale hair damp and flattened from being plunged +in the bowl where he had washed. Cadfael took pleasure in observing him from a +distance, himself unobserved. So wherever he had been hiding himself yesterday, +he was still here in safety, and, moreover, developing a wholly creditable +self-respect, with which guilt, or so it seemed to Cadfael, must be +incompatible.

+ +

Brother Anselm, detecting the presence of his truant in church only when a +high, hesitant voice joined in the singing, was similarly reassured and +comforted. Prior Robert heard the same voice, looked round in incredulous +displeasure, and frowned upon a dismayed Brother Jerome, who had so misled him. +They still had the thorn in the flesh, thanksgiving had been premature.

+ +

The lay brothers were planting out more seedlings in a large patch along the +Gaye that day, and sowing a later field of pease for succession, to follow when +those by the Meole brook were harvested. Cadfael went out after dinner to view +the work. After the night’s soft shower the day was brilliant, sunlit and +serene, but the earlier rains were still coming down the river from the +mountains of Wales in their own good time, and the water was lapping into the +grass where the meadow sloped smoothly down, and gnawing gently under the lip +of the bank where it could not reach the turf. The length of a man’s hand +higher since two days ago, but always with this sunlit innocence upon it, as if +it would be ashamed to endanger the swimming urchins, and could not possibly be +thought capable of drowning any man. And this as perilous a river as any in the +land, as treacherous and as lovely.

+ +

It was pleasure to walk along the trodden path that was only a paler line in +the turf, following the fast, quiet flood downstream. Cadfael went with his +eyes on the half-turgid, half-clear eddies that span and mummured under the lip +of green, a strong current here hugging this shore. Across the stream, so +silent and so fast, the walls of Shrewsbury loomed, at the crest of a steep +green slope of gardens, orchards and vineyard, and further downstream fused +into the solid bulk of the king’s castle, guarding the narrow neck of land that +broke Shrewsbury’s girdle of water.

+ +

On this near shore Cadfael had reached the limit of the abbey orchards, +where lush copses began, fringing the abbey’s last wheatfield, and the old, +disused mill jutted over the river. He passed, threading the trees and bushes, +and went on a short way, to where the level of land dipped to water-level in a +little cove, shallowly covered by clear water now, the driving current spinning +in and out again just clear of disturbing the gravel bottom. Things tended to +come in here and be cast ashore if the Severn was in spate, and enclosing +shoulders of woodland screened whatever came.

+ +

And something wholly unforeseen had come, and was lying here in uneasy +repose, sprawled face-down, head butted into the gravelly calm of the bank. A +solid body in good homespun cloth, shortish and sturdy, a round bullish head +with floating, grizzled brown hair, thinning at the crown. Splayed arms, +languidly moving in the gentle stir of the shallows, clear of the deadly +purposeful central flow, fingered and fumbled vaguely at the fine gravel. Squat +legs, but drawn out by the hungry current tugging at their toes, stretched +towards open water. Cast up dead, all four limbs stirred and strained to prove +him living.

+ +

Brother Cadfael kilted his habit to the knee, plunged down the gentle slope +into the water, took the body by the bunched capuchon swaying at his neck and +the leather belt at his waist, and hoisted him gradually clear of the surface, +to disturb as little as possible the position in which he had been swept +ashore, and whatever traces the river had spared in his clothing, hair and +shoes. No haste to feel for any life here, it had been gone for some time. Yet +he might have something to tell even in his final silence.

+ +

The dead weight sagged from Cadfael’s hands. He drew it, streaming, up the +first plane of grass, and there let it sink in the same shape it had had in the +river. Who knew where it had entered the water and how?

+ +

As for naming him, there was no need to turn up that sodden face to the +light of day, not yet. Cadfael recognised the russet broadcloth, the sturdy +build, the round, turnip head with its thinning crown and bushy brown hedge of +hair all round the shiny island of bone. Only two mornings ago he had passed +the time of day with this same silenced tongue, very fluent and roguish then, +enjoying its mischief without any great malice.

+ +

Baldwin Peche had done with toothsome scandal, and lost his last tussle with +the river that had provided him with so many fishing sorties, and hooked him to +his death in the end.

+ +

Cadfael hoisted him by the middle, marked the derisory flow from his mouth, +barely moistening the grass, and let him down carefully in the same form. He +was a little puzzled to find so meagre a flow, since even the dead may give +back the water they have swallowed, for at least a brief while after their +death. This one had left a shallow shape scooped in the gravel of the cove, +which was hardly disturbed by currents. His outlines in the grass now +duplicated the outline he had abandoned there.

+ +

Now how had Baldwin Peche come to be beached here like a landed fish? Drunk +and careless along the riverside at night? Spilled out of a boat while fishing? +Or fallen foul of a footpad in one of the dark alleys and tipped into the water +for the contents of his purse? Such things did occasionally happen even in a +well-regulated town on dark enough nights, and there did seem to be a thicker +and darker moisture in the grizzled hair behind Peche’s right ear, as though +the skin beneath was broken. Scalp wounds tend to bleed copiously, and even +after some hours in the water or cast up here traces might linger. He was +native-born, he knew the river well enough to respect it, all the more as he +acknowledged he was a weak swimmer.

+ +

Cadfael threaded the belt of bushes to have a clear view over the Severn, +upstream and down, and was rewarded by the sight of a coracle making its way +against the current, turning and twisting to make use of every eddy, bobbing +and dancing like a shed leaf, but always making progress. There was only one +man who could handle the paddle and read the river with such ease and skill, +and even at some distance the squat, dark figure was easily recognisable. Madog +of the Dead-Boat was as Welsh as Cadfael himself, and the best-known waterman +in twenty miles of the Severn’s course, and had got his name as a result of the +cargo he most often had to carry, by reason of his knowledge of all the places +where missing persons, thought to have been taken by the river whether in flood +or by felony, were likely to fetch up. This time he had no mute passenger +aboard; his natural quarry was here waiting for him.

+ +

Cadfael knew him well and for no ascertainable reason, except the customary +association of Madog with drowned men, took for granted that even in this case +the connection must hold good. He raised a hail and waved an arm as the coracle +drew nearer, picking its feathery way across the mid-stream current where it +was diffused and moderate. Madog looked up, knew the man who beckoned him in, +and with a sweep of his paddle brought his boat inshore, clear of the +deceitfully silent and rapid thrust that sped down-river, leaving this cove so +placid and clear. Cadfael waded into the shallows to meet him, laying a hand to +the rim of hide as Madog hopped out nimbly to join him, his brown feet bare.

+ +

“I thought I knew that shaven sconce of yours,” he said heartily, and +hoisted his cockle-shell of withies and hide on to his shoulder to heft it +ashore. “What is it with you? When you call me, I take it there’s a sound +reason.”

+ +

“Sound enough,” said Cadfael. “I think I may have found what you were +looking for.” He jerked his head towards the plane of grass above, and led the +way up without more words. They stood together over the prone body in +thoughtful silence for some moments. Madog had taken note in one glance of the +position of the head, and looked back to the gravelled shore under its liquid +skin of water. He saw the shadowy shape left in the fine shale, and the mute, +contained violence of the current that swept past only a man’s length away from +that strange calm.

+ +

“Yes. I see. He went into the water above. Perhaps not far above. There’s a +strong tow under that bank, upstream from here a piece, under the castle. Then +it could have brought him across and thrown him up here just as he lies. A +good, solid weight, head-first into the bank. And left him stranded.”

+ +

“So I thought,” said Cadfael. “You were looking for him?” People along the +waterside who had kin go missing usually sought out Madog before they notified +the provost or the sheriff’s sergeant.

+ +

“That journeyman of his sent after me this morning. It seems his master went +off yesterday before noon, but nobody wondered, he did the like whenever he +chose, they were used to it. But this morning he’d never been back. There’s a +boy sleeps in his shop, he was fretting over it, so when Boneth came to work +and no locksmith he sent the lad to me. This one here liked his bed, even if he +sometimes came to it about dawn. Not the man to go hungry or dry, either, and +the ale-house he favoured hadn’t seen him.”

+ +

“He has a boat,” said Cadfael. “A known fisherman.”

+ +

“So I hear. His boat was not where he keeps it.”

+ +

“But you’ve found it,” said Cadfael with conviction.

+ +

“A half-mile down-river, caught in the branches where the willows overhang. And +his rod snagged by the hook and trailing. The boat had overturned. He ran a +coracle, like me. I’ve left it beached where I found it. A tricky boat,” said +Madog dispassionately, “if he hooked a lusty young salmon. The spring ones are +coming. But he knew his craft and his sport.”

+ +

“So do many and take the one chance that undoes them.”

+ +

“We’d best get him back,” said Madog, minding his business like any good +master-craftsman. “To the abbey? It’s the nearest. And Hugh Beringar will have +to know. No need to mark this place, you and I both know it well, and his marks +will last long enough.”

+ +

Cadfael considered and decided. “You’ll get him home best afloat, and it’s +your right. I’ll follow ashore and meet you below the bridge, we shall make +much the same time of it. Keep him as he lies, Madog, face-down, and note what +signs he leaves aboard.”

+ +

Madog had at least as extensive a knowledge of the ways of drowned men as +Cadfael. He gave his friend a long, thoughtful look, but kept his thoughts to +himself, and stooped to lift the shoulders of the dead man, leaving Cadfael the +knees. They got him decently disposed into the light craft. There was a fee for +every Christian body Madog brought out of the river, he had indeed a right to +it. The duty had edged its way in on him long ago, almost unaware, but other +men’s dying was the better part of his living now. And an honest, useful, +decent man, for which many a family had been thankful.

+ +

Madog’s paddle dipped and swung him across the contrary flow, to use the +counter-eddies in moving up-river. Cadfael took a last look at the cove and the +level of grass above it, memorised as much of the scene as he could, and set +off briskly up the path to meet the boat at the bridge.

+ +

The river was fast and self-willed, and by hurrying, Cadfael won the race, +and had time to recruit three or four novices and lay brothers by the time +Madog brought his coracle into the ordered fringes of the Gaye. They had an +improvised litter ready, they lifted Baldwin Peche onto it, and bore him away +up the path to the Foregate and across to the gatehouse of the abbey. A nimble +and very young novice had been sent in haste to carry word to the +deputy-sheriff to come to the abbey at Brother Cadfael’s entreaty.

+ +

But for all that, no one knew how, somehow the word had gone round. By the +time Madog arrived, so had a dozen idle observers, draped over the downstream +parapet of the bridge. By the time the bearers had got their burden to the +level of the Foregate and turned towards the abbey, the dozen had become a +score, and drifted in ominous quietness towards the end of the bridge, and +there were a dozen more gradually gathering behind them, emerging from the town +gate. When they reached the abbey gatehouse, which could not well be closed +against any who came in decorous silence and apparent peace, they had between +forty and fifty souls hovering at their heels and following them within. The +weight of their foreboding, accusation and self-righteousness lay heavy on the +nape of Cadfael’s neck as the litter was set down in the great court. When he +turned to view the enemy, for no question but they were the enemy, the first face +he saw, the first levelled brow and vengeful eye, was that of Daniel Aurifaber.

+
+
+

Chapter Seven

+ +

« ^ »

+ +

Tuesday: from afternoon to night

+ +

They came +crowding close, peering round Madog and Cadfael to confirm what they already +knew. They passed the word back to those behind, in ominous murmurs that +swelled into excited speculation in a matter of moments. Cadfael caught at the +sleeve of the first novice who came curiously to see what was happening.

+ +

“Get Prior Robert and sharp about it. We’re likely to need some other +authority before Hugh Beringar gets here.” And to the litter-bearers, before +they could be completely surrounded: “Into the cloister with him, while you +can, and stand ready to fend off any who try to follow.”

+ +

The sorry cortege obediently made off into cover in some haste, and though +one or two of the younger fellows from the town were drawn after by gaping +curiosity to the threshold of the cloister, they did not venture further, but +turned back to rejoin their friends. An inquisitive ring drew in about Cadfael +and Madog.

+ +

“That was Baldwin Peche the locksmith you had there,” said Daniel, not +asking, stating. “Our tenant. He never came home last night. John Boneth has +been hunting high and low for him.”

+ +

“So have I,” said Madog, “at that same John’s urging. And between the two of +us here we’ve found both the man and his boat.”

+ +

“Dead.” That was not a question either.

+ +

“Dead, sure enough.”

+ +

By that time Prior Robert had been found, and came in haste with his dutiful +shadow at his heels. Of the interruptions to his ordered, well-tuned life +within here, it seemed, there was to be no end. He had caught an unpleasant +murmur of ‘Murder!’ as he approached, and demanded in dismay and displeasure +what had happened to bring this inflamed mob into the great court. A dozen +voices volunteered to tell him, disregarding how little they themselves knew +about it.

+ +

“Father Prior, we saw our fellow-townsman carried in here, dead…”

+ +

“No one had seen him since yesterday…”

+ +

“My neighbour and tenant, the locksmith,” cried Daniel. “Father robbed and +assaulted, and now Master Peche fetched in dead!”

+ +

The prior held up a silencing hand, frowning them down. “Let one speak. +Brother Cadfael, do you know what this is all about?”

+ +

Cadfael saw fit to tell the bare facts, without mention of any speculations +that might be going on in his own mind. He took care to be audible to them all, +though he doubted if they would be setting any limits to their own +speculations, however careful he might be. “Madog here has found the man’s boat +overturned, down-river past the castle,” he concluded. “And we have sent to +notify the deputy-sheriff, the matter will be in his hands now. He should be +here very soon.”

+ +

That was for the more excitable ears. There were some wild youngsters among +them, the kind who are always at leisure to follow up every sensation, who +might well lose their heads if they sighted their scapegoat. For the +implication was already there, present in the very air. Walter robbed and +battered, now his tenant dead, and all evil must light upon the same head.

+ +

“If the unfortunate man drowned in the river, having fallen from his boat,” +said Robert firmly, “there can be no possibility of murder. That is a foolish +and wicked saying.”

+ +

They began to bay from several directions. “Father Prior, Master Peche was +not a foolhardy man…”

+ +

“He knew the Severn from his childhood…”

+ +

“So do many,” said Robert crisply, “who fall victim to it in the end, men no +more foolhardy than he. You must not attribute evil to what is natural +misfortune.”

+ +

“And why should natural misfortune crowd so on one house?” demanded an +excited voice from the rear. “Baldwin was a guest the night Walter was struck +down and his coffer emptied.”

+ +

“And next-door neighbour, and liked to nose out whatever was hidden. And +who’s to say he didn’t stumble on some proof that would be very bad news to the +villain that did the deed, and lurks here swearing to his innocence?”

+ +

It was out, they took it up on all sides. “That’s how it was! Baldwin found +out something the wretch wouldn’t have been able to deny!”

+ +

“And he’s killed the poor man to stop his mouth…”

+ +

“A knock on the head and souse into the river…”

+ +

“No trick to turn his boat loose for the river to take down after him…”

+ +

Cadfael was relieved to see Hugh Beringar riding briskly in at the gatehouse +then with a couple of officers behind him. This was getting all too +predictable. When men have elected a villain, and one from comfortably outside +their own ranks, without roots or kin, they need feel nothing for him, he is +hardly a man, has no blood to be shed or heart to be broken, and whatever else +needs a scapegoat will be laid on him heartily and in the conviction of +righteousness. Nor will reason have much say in the matter. But he raised his +voice powerfully to shout them down: “The man you accuse is absolutely clear of +this, even if it were murder. He is in sanctuary here, dare not leave the +precinct, and has not left it. The king’s officers wait for him outside, as you +all know. Be ashamed to make such senseless charges!”

+ +

He said afterwards, rather resignedly than bitterly, that it was a precise +measure of Liliwin’s luck that he should appear innocently from the cloister at +that moment, bewildered and shocked by the incursion of a dead body into the +pale, and coming anxiously to enquire about it, but utterly ignorant of any +connection it might be thought to have with him. He came hastening out of the +west walk, solitary, apart, marked at once by two or three of the crowd. A howl +went up, hideously triumphant. Liliwin took it like a great blast of cold wind +in his face, shrank and faltered, and his countenance, healing into smooth +comeliness these last two days, collapsed suddenly into the disintegration of +terror.

+ +

The wildest of the young bloods moved fast, hallooing, but Hugh Beringar +moved faster. The raw-boned grey horse, his favourite familiar, clattered +nimbly between quarry and hounds, and Hugh was out of the saddle with a hand on +Liliwin’s shoulder, in a grip that could have been ambiguously arrest or +protection, and his neat, dark, saturnine visage turned blandly towards the +threatening assault. The foremost hunters froze discreetly, and thawed again +only to draw back by delicate inches from challenging his command.

+ +

The nimble young novice had acquitted himself well, and shown an excellent +grasp of his charge, for Hugh had the half of it clear in his mind already and +understood its perilous application here. He kept his hold—let them read it +however they would—on Liliwin throughout the questioning that followed, and +listened as narrowly to Daniel Aurifaber’s heated witness as to Cadfael’s +account.

+ +

“Very well! Father Prior, it would be as well if you yourself would convey +this in due course to the lord abbot. The drowned man I must examine, as also +the place where he was cast ashore and that where his boat came to rest. I must +call upon the help of those who found out these matters. For the rest of you, +if you have anything to say, say it now.”

+ +

Say it they did, intimidated but still smouldering, and determined to pour +out their heat. For this was no chance death in the river, of that they were +certain. This was the killing of a witness, close, curious, likely of all men +to uncover some irrefutable evidence. He had found proof of the jongleur’s +strenuously-denied guilt, and he had been slipped into the Severn to drown +before he could open his mouth. They began by muttering it, they ended by +howling it. Hugh let them rave. He knew they were no such monsters as they made +themselves out to be, but knew, too, that given a following wind and a rash +impulse, they could be, to their own damage and that of every other man.

+ +

They ran themselves out of words at length, and dwindled like sails bereft +of wind.

+ +

“My men have been camped outside the gates here,” said Hugh then, calmly, “all +this while and have seen no sign of this man you accuse. To my knowledge he has +not set foot outside these walls. How, then, can he have had any hand in any +man’s death?”

+ +

They had no answer ready to that, though they sidled and exchanged glances +and shook their heads as though they knew beyond doubt that there must be an +answer if they could only light on it. But out of the prior’s shadow the +insinuating voice of Brother Jerome spoke up mildly:

+ +

“Pardon, Father Prior, but is it certain that the young man has been every +moment within here? Only recall, last night Brother Anselm was enquiring after +him and had not seen him since just after noon, and remarked, moreover, that he +did not come to the kitchen for his supper as is customary. And being concerned +for any guest of our house, I felt it my duty to look for him and did so +everywhere. That was just when twilight was falling. I found no trace of him +anywhere within the walls.”

+ +

They took it up gleefully on the instant and Liliwin, as Cadfael observed +with a sigh, shook and swallowed hard, and could not get out a word, and drops +of sweat gathered on his upper lip and ran down, to be licked off feverishly.

+ +

“You see, the good brother says it! He was not here! He was out about his +foul business!”

+ +

“Say rather,” Prior Robert reproached gently, “that he could not be found.” +But he was not altogether displeased.

+ +

“And go without his supper? A half-starved rat scorn his food unless he had +urgent business elsewhere?” cried Daniel fiercely.

+ +

“Very urgent! He took his life in his hands to make sure Baldwin should not +live to speak against him.”

+ +

“Speak up!” said Hugh drily, shaking Liliwin by the shoulder. “You have a +tongue, too. Did you leave the abbey enclave at any time?”

+ +

Liliwin gulped down gall, hung in anguished silence a moment, and got out in +a great groan: “No!”

+ +

“You were within here yesterday, when you were sought and could not be +found?”

+ +

“I didn’t want to be found. I hid myself.” His voice was firmer when he had +at least a morsel of truth to utter. But Hugh pressed him still.

+ +

“You have not once set foot outside this pale since you took refuge here?”

+ +

“No, never!” he gasped, and dragged in breath as though he had run a great +way.

+ +

“You hear?” said Hugh crisply, putting Liliwin aside and behind him. “You +have your answer. A man penned securely here cannot have committed murder +outside, even if this proves to be murder, as at this moment there is no proof +whatsoever. Now go, get back to your own crafts, and leave to the law what is +the law’s business. If you doubt my thoroughness, try crossing me.” And to his +officers he said simply: “Clear the court of those who have no business here. I +will speak with the provost later.”

+ +

In the mortuary chapel Baldwin Peche lay stripped naked, stretched now on +his back, while Brother Cadfael, Hugh Beringar, Madog of the Dead-Boat and +Abbot Radulfus gathered about him attentively. In the corners of his eyes, now +closed, traces of ingrained mud lingered, drying, like the pigments vain women +use to darken and brighten their eyes. From his thick tangle of grizzled brown +hair Cadfael had coaxed out two or three strands of water crowfoot, cobweb-fine +stems with frail white flowers withering into veined brown filaments as they +died, and a broken twig of alder leaves. There was nothing strange in either of +those. Alders clustered in many places along the riverside, and this was the +season when delicate rafts of crowfoot swayed and trembled wherever there were +shallows or slower water.

+ +

“Though the water where I found him,” said Cadfael, “runs fast, and will not +anchor these flowers. The opposite bank I fancy, harbours them better. That is +reasonable—if he launched his boat to go fishing it would be from that bank. +And now see what more he has to show us.”

+ +

He cupped a palm under the dead man’s cheek, turned his face to the light, +and hoisted the bearded chin. The light falling into the stretched cavities of +the nostrils showed them only as shallow hollows silted solid with river mud. +Cadfael inserted the stem of the alder twig into one of them, and scooped out a +smooth, thick slime of fine gravel and a wisp of crowfoot embedded within it.

+ +

“So I thought, when I hefted him to empty out the water from him and got +only a miserable drop or two. The drainings of mud and weed, not of a drowned +man.” He inserted his fingers between the parted lips, and showed the teeth +also parted, as if in a grimace of pain or a cry. Carefully he drew them wider. +Tendrils of crowfoot clung in the large, crooked teeth. Those peering close +could see that the mouth within was clogged completely with the debris of the +river.

+ +

“Give me a small bowl,” said Cadfael, intent, and Hugh was before Madog in +obeying. There was a silver saucer under the unlighted lamp on the altar, the +nearest receptacle, and Abbot Radulfus made no move to demur. Cadfael eased the +stiffening jaw wider, and with a probing finger drew out into the bowl a thick +wad of mud and gravel, tinted with minute fragments of vegetation. “Having +drawn in this, he could not draw in water. No wonder I got none out of him.” He +felt gently about the dead mouth, probing out the last threads of crowfoot, +fine as hairs, and set the bowl aside.

+ +

“What you are saying,” said Hugh, closely following, “is that he did not +drown.”

+ +

“No, he did not drown.”

+ +

“But he did die in the river. Why else these river weeds deep in his +throat?”

+ +

“True. So he died. Bear with me, I am treading as blindly as you. I need to +know, like you, and like you, I must examine what we have.” Cadfael looked up at +Madog, who surely knew all these signs at least as well as any other man +living. “Are you with me so far?”

+ +

“I am before you,” said Madog simply. “But tread on. For a blind man you +have not gone far astray.”

+ +

“Then, Father, may we now turn him again on his face, as I found him?”

+ +

Radulfus himself set his two long, muscular hands either side of the head, +to steady the dead man over, and settled him gently on one cheekbone.

+ +

For all his self-indulgent habits of life, Baldwin Peche showed a strong, +hale body, broad-shouldered, with thick, muscular thighs and arms. The +discolorations of death were beginning to appear on him now, and they were +curious enough. The broken graze behind his right ear, that was plain and +eloquent, but the rest were matter for speculation.

+ +

“That was never got from any floating branch,” said Madog with certainty, “nor +from being swept against a stone, either, not in that stretch of water. Up here +among the islands I wouldn’t say but it might be possible, though not likely. +No, that was a blow from behind, before he went into the water.”

+ +

“You are saying,” said Radulfus gravely, “that the charge of murder is +justified.”

+ +

“Against someone,” said Cadfael, “yes.”

+ +

“And this man was indeed next-door neighbour to the household that was +robbed, and may truly have found out something, whether he understood its +meaning or not, that could shed light on that robbery?”

+ +

“It is possible. He took an interest in other men’s business,” agreed +Cadfael cautiously.

+ +

“And that would certainly be a strong motive for his removal, if the guilty +man got to know of it,” said the abbot, reflecting. “Then since this cannot be +the work of one who was here within our walls throughout, it is strong argument +in favour of the minstrel’s innocence of the first offence. And somewhere at +large is the true culprit.”

+ +

If Hugh had already perceived and accepted the same logical consequence, he +made no comment on it. He stood looking down at the prone body in frowning +concentration. “So it would seem he was hit on the head and tossed into the +river. And yet he did not drown. What he drew in, in his fight for breath—in +his senses or out—was mud, gravel, weed.”

+ +

“You have seen,” said Cadfael. “He was smothered. Held down somewhere in the +shallows, with his face pressed into the mud. And set afloat in the river +afterwards, with the intent he should be reckoned as one more among the many +drowned in Severn. A mistake! The current cast him up before the river had time +to wash away all these evidences of another manner of death.”

+ +

He doubted, in fact, if they would ever have been completely washed away, +however long the body had been adrift. The stems of crowfoot were very +tenacious. The fine silt clung tightly where it had been inhaled in the +struggle for breath. But what was more mysterious was the diffused area of +bruising that spread over Peche’s back at the shoulder-blades, and the two or +three deep indentations in the swollen flesh there. In the deepest the skin was +broken, only a tiny lesion, as though something sharp and jagged had pierced him. +Cadfael could make nothing of these marks. He memorised them and wondered.

+ +

There remained the contents of the silver bowl. Cadfael took it out to the +stone basin in the middle of the garth and carefully sluiced away the fine +silt, drawing aside and retaining the fragments of weed. Fine threads of +crowfoot, a tiny, draggled flower, a morsel of an alder leaf. And something +else, a sudden speck of colour. He picked it out and dipped it into the water +to wash away the dirt that clouded it, and there it lay glistening in the palm +of his hand, a mere scrap, two tiny florets, the tip of a head of flowers of a +reddish purple colour, speckled at the lip with a darker purple and a torn +remnant of one narrow leaf, just large enough to show a blackish spot on its green.

+ +

They had followed him out and gathered curiously to gaze. “Fox-stones, we +call this,” said Cadfael, “for the two swellings at its root like pebbles. The +commonest of its kind, and the earliest, but I don’t recall seeing it much +here. This, like the broken twig of alder, he took down with him when he was +pushed into the water. It might be possible to find that place somewhere on the +town bank—where crowfoot and alder and fox-stones all grow together.”

+ +

The place where Baldwin Peche had been cast ashore had little to tell beyond +what it had already told. The spot where Madog had turned down the dead man’s +coracle on the meadow grass was well down-river, and so feather-light a boat, +loose without a man’s weight aboard, might well have gone on bobbing gaily +downstream a mile or more beyond, before the first strong curve and encroaching +sandbank would inevitably have arrested it. They would have to comb the town +bank, Madog reckoned, from below the Watergate, to establish where he had been +assaulted and killed. A place where crowfoot grew inshore under alders, and +fox-stones were in flower close to the very edge of the water.

+ +

The first two could be found together all along the reach. The third might +occur in only one place.

+ +

Madog would search the riverside, Hugh would question the Aurifaber +household and the immediate neighbours, as well as the tavern-keepers of the +town, for everything they knew about the recent movements of Baldwin Peche: +where he had last been seen, who had spoken with him, what he had had to say. +For someone, surely, must have seen him after he left his shop about +mid-morning of the previous day, which was the last John Boneth knew of him.

+ +

Meantime, Cadfael had business of his own, and much to think about. He came +back from the riverside too late for Vespers, but in time to visit his workshop +and make sure all was in order there before supper. Brother Oswin, left in +charge alone, was developing a deft touch and a proprietorial pride. He had not +broken or burned anything for several weeks.

+ +

After supper Cadfael went in search of Liliwin, and found him sitting in +deep shadow in the darkest corner of the porch, drawn up defensively against +the stone with his arms locked about his knees. At this hour the light was too +far gone for work to proceed on the mending of his rebec, or his new studies +under Brother Anselm, and it seemed that the day’s alarms had driven him back +into distrust and despair, so that he hunched himself as small as possible into +his corner and kept a wary face against the world. Certainly he gave Cadfael a +bright, nervous, sidelong flash of his eyes as the monk hitched his habit +comfortably and sat down beside him.

+ +

“Well, young man, have you fetched your supper tonight?” said Cadfael +placidly.

+ +

Liliwin acknowledged that with a silent nod, watching him warily.

+ +

“It seems you did not yesterday, and Brother Jerome tells us that a +maidservant came to visit you in the afternoon and brought you a basket of food +from her lady’s table. He had, he said, occasion to admonish you both.” The silence +beside him was charged and uneasy. “Now, granted Brother Jerome is uncommonly +good at finding grounds for admonishment, yet I fancy there is but one +maidservant whose presence here would have caused him qualms for the propriety +of your conduct—let alone the well-being of your soul.” It was said with a +smile in his voice, but he did not miss the slight shudder that convulsed the +thin body beside him or the stiffening of the hands that were clasped so +tightly round Liliwin’s knees. Now why in the world should the lad quake at the +mention of his soul’s health, just when Cadfael was becoming more and more +convinced that he had no guilt whatever upon his conscience, bar an +understandable lie or two.

+ +

“Was it Rannilt?”

+ +

“Yes,” said Liliwin, just audibly.

+ +

“She came with good leave? Or of her own accord?”

+ +

Liliwin told him, in as few words as possible.

+ +

“So that was how it befell. And Jerome bade her do her errand and go, and +stood over you to make sure she obeyed. And it was from that hour, as I +understand—after he had witnessed her going—that no one saw you again +until Prime this morning. Yet you say you were here within the pale and what +you say, that I accept. Did you speak?”

+ +

“No,” said Liliwin, none too happily. Not speech, exactly, but a small, +shamed sound hurriedly suppressed.

+ +

“You let her go somewhat tamely, did you not?” remarked Cadfael critically. +“Seeing the magnitude of the step she had taken for you.”

+ +

The evening was closing down tranquilly all round them, there was no one +else to hear, and Liliwin had spent much of the day wrestling alone with the +belated conviction of his mortal sin. Terror of men was surely enough to bear, +without being suddenly visited by the terror of damnation, let alone the awful +sense of having brought about the damnation of another person as dear to him as +himself. He uncurled abruptly from his dark corner, slid his legs over the edge +of the stone bench, and clutched Cadfael impulsively by the arm.

+ +

“Brother Cadfael, I want to tell you… I must tell someone! I did—we +did, but the fault was mine!—we did a terrible thing. I never meant it, but she +was going away from me, and I might never see her again, and so it happened. A +mortal sin and I’ve caused her to share in it!” The words spurted out like +blood from a new wound, but the first flow eased him. From incoherent he grew +quiet, and his shaking subsided and was gone. “Let me tell you, and then do +whatever you think is just. I couldn’t bear it that she must go so soon, and it +might be for ever. We went through the church, and I hid her within there, +behind the altar in the transept chapel. There’s a space behind there, I found +it when I came new here and was afraid they might come for me in the night. I +knew I could creep in there, and she is smaller than I. And when that brother +had gone away, I went back to her there. I took my blankets in with me, and the +new clothes she brought me—it’s hard and chill on the stone. All I wanted,” +said Liliwin simply, “was to be with her as long as we dared. We did not even +talk very much. But then we forgot where we were, and what was due…”

+ +

Brother Cadfael said no word either to help or check him, but waited in +silence.

+ +

“I couldn’t think of anything but that she would go away, and I might never +be with her again,” blurted Liliwin miserably, “and I knew she was in the +selfsame pain. We never intended evil, but we committed a terrible sacrilege. +Here in the church, behind one of the holy altars—We couldn’t bear it… We lay +together as lovers do!”

+ +

He had said it, it was out, the very worst of it. He sat humbly waiting for +condemnation, resigned to whatever might come, even relieved at having shifted +the burden to other shoulders. There was no exclamation of horror, but this +brother was not so given to prodigal admonishment as that sour one who had +frowned on Rannilt.

+ +

“You love this girl?” asked Cadfael after some thought, and very placidly.

+ +

“Yes, I do love her! With all my heart I want her for my wife. But +what is there for her if I am brought out of here to trial and the matter goes +blackly for me? As they mean it should! Don’t let it be known that she has been +with me. Her hopes of marriage are wretched enough, a poor servant-girl without +folk of her own. I don’t want to damage them further. She may still get a +decent man, if I…” He let that die away unfinished. It was no comforting +thought.

+ +

“I think,” said Cadfael, “she would rather have the man she has already +chosen. Where mutual love is, I find it hard to consider any place too holy to +house it. Our Lady, according to the miracles they tell of her, has been known +to protect even the guilty who sinned out of love. You might try a few prayers +to her, that will do no harm. Don’t trouble too much for what was done under +such strong compulsion and pure of any evil intent. And how long, then,” +enquired Cadfael, eyeing his penitent tolerantly, “did you remain hidden there? +Brother Anselm was worried about you.”

+ +

“We fell asleep, both of us.” Liliwin shook again at the memory. “When we +roused, it was late and dark, they were singing Compline. And she had to go back +all that way into the town in the night!”

+ +

“And you let her go alone?” demanded Cadfael with deceitful indignation.

+ +

“I did not! What do you take me for?” Liliwin had flared and fallen into the +snare before he stopped to think, and it was too late to take it back. He sat +back with a deflated sigh, stooping his face into deeper shadow.

+ +

“What do I take you for?” Cadfael’s smile was hidden by the dusk. “A bit of +a rogue, perhaps, but no worse than the most of us. A bit of a liar when the +need’s great enough, but who isn’t? So you did slip out of here to take the +child home. Well, I think the better of you for it, it must have cost you some +terrors.” And provided a salutary stiffening of self-respect, he thought but +did not say.

+ +

In a small and perversely resentful voice Liliwin asked: “How did you know?”

+ +

“By the effort it cost you to get the denial out. For you will never make a +really good liar, lad, and the more you hate doing it, the worse +you’ll manage, and it seems to me you’ve taken strongly against lying these +last few days. How did you contrive to get out and in again?”

+ +

Liliwin took heart and told him, how the new clothes had got him past the +guards on the heels of the worshippers, and how he had taken Rannilt to her +very doorway, and made his way back under cover of the returning lay servants. +What had passed between himself and Rannilt on the way he kept to himself, and +it did not enter his mind to say any word of what else he had noticed, until +Cadfael took him up alertly on that very subject.

+ +

“So you were there, outside the shop, about an hour after Compline?” Night +is the favoured time for ridding oneself of enemies, and this was the one night +that had passed since Baldwin Peche was last seen alive.

+ +

“Yes, I watched her safe into the courtyard. Only I fret,” said Liliwin, “over +what sort of welcome she may have found. Though her lady did say she might stay +the day out. I hope no one was angry with her.”

+ +

“Well, since you were there, did you see ought of anything or anyone +stirring about the place?”

+ +

“I did see one man who was out and about,” said Liliwin, remembering. “It +was after Rannilt had gone in. I was standing opposite, in a dark doorway, and +Daniel Aurifaber came out through the passage, and went away to the left along +the lane. He can’t have gone far without turning aside, for when I went back to +the Cross and down the Wyle he was gone already, I never saw sign of him +after.”

+ +

“Daniel? You’re sure it was he?” That young man had been very prompt and +present this afternoon, as soon as the usual idlers saw a body being lifted +ashore under the bridge. Very prompt and very forward to lead the accusers who +made haste to fling this, like the other offences, on the stranger’s head, +reason or no reason, sanctuary or no sanctuary.

+ +

“Oh, yes, there’s no mistaking him.” He was surprised that such a point +should be made of it. “Is it important?”

+ +

“It may be. But no matter now. One thing you haven’t said,” pointed out +Cadfael gravely, “and yet I’m sure you are not so dull but you must have +thought on it. Once you were out of here and no alarm, and the night before +you, you might have made off many miles from here, and got clean away from your +accusers. Were you not tempted?”

+ +

“So she prompted me, too,” said Liliwin, remembering, and smiled. “She +urged me to go while I could.”

+ +

“Why did you not?”

+ +

Because she did not truly want me to, thought Liliwin, with a joyful lift of +the heart for all his burdens. And because if ever she does come to me, it +shall not be to an accused felon, but to a man acknowledged honest before the world. +Aloud he voiced only the heart of that revelationary truth: “Because now I +won’t go without her. When I leave—if I leave—I shall take Rannilt +with me.”

+
+
+

Chapter Eight

+ +

« ^ »

+ +

Wednesday

+ +

Hugh sought +out Cadfael after chapter the next morning for a brief conference in his +workshop in the herbarium.

+ +

“They’re all in a tale,” said Hugh, leaning back with a cup of Cadfael’s +latest-broached wine under the rustling bunches of last year’s harvest of +herbs. “All insistent that this death must be linked to what happened at the +young fellow’s wedding feast. But since they’re all of them obsessed with +money, their money—except, perhaps, the daughter, who curls her lip +very expressively but says little, and certainly nothing against her kin—they +can think of nothing but their grievance and every other man must be as intent +on it as they are. Yet there’s profit and profit, and this locksmith’s business +does very nicely for itself, and now there’s no kith nor kin to take it over, +and it seems to be common knowledge the man had commended his journeyman to +take the shop over after him. This young Boneth has been doing most of the work +now above two years, he deserves he should get the credit. As right and +virtuous a young man as ever I saw, to all appearances, but who’s to be sure he +didn’t get tired of waiting? And we’d best bear in mind another truth—it was +Baldwin Peche made the lock and keys for that strong-box of Aurifaber’s.”

+ +

“There’s a boy runs the errands and sleeps there in the shop,” said Cadfael. +“Has he ought to say?”

+ +

“The dark boy, the simpleton? I wouldn’t say his memory goes back farther +than a day or so, but he’s positive his master did not come back to his shop +after he looked in at mid-morning, the day before he was fished out of the Severn. +They were used to his absences by day, but the boy was anxious when there was +no return at twilight. He didn’t sleep. I would take his word for it there was +no disturbance, no prowling about that burgage during the night. Nor are we the +nearer knowing just when the man died, though the night would seem to be when +he was set adrift, and the boat, too. There was no overturned coracle sighted +down the Severn during the day—either day.”

+ +

“You’ll be going back there, I suppose,” said Cadfael. There had been very +little time the previous day for hunting out all the neighbours to testify. “I’ve +an errand there myself to the old dame tomorrow, but no occasion to go that way +today. Give an eye for me to the little Welsh girl, will you, see in what +spirits she is, and whether they’re being rough or smooth with her.”

+ +

Hugh cocked a smiling eye at him. “Your countrywoman, is she? To judge by +the way I heard her singing away about her pot-scouring, last night, she’s in +good enough heart.”

+ +

“Singing, was she?” That would come as very welcome news to that draggled +sparrow in his sanctuary cage here. Evidently no hardship more than normal had +fallen upon Rannilt for her day of freedom. “Good, that answers me very +properly. And, Hugh, if you’ll take a nudge from me without asking any +questions as to where I picked up the scent—probe around as to whether anyone +on that street saw Daniel Aurifaber slipping out in the dark an hour past +Compline, when he should have been snug in bed with his bride.”

+ +

Hugh turned his black head sharply, and gave his friend a long and quizzical +look. “That night?”

+ +

“That night.”

+ +

“Three days married!” Hugh grimaced and laughed. “I’d heard the young man +has the name for it. But I take your meaning. There may be other reasons for leaving +a new wife to lie cold.”

+ +

“When I spoke with him,” said Cadfael, “he made no secret of it that he +heartily disliked the locksmith. Though had his dislike had a solid core, and +gone as far as congealing into hate, I think he might have been less voluble +about it.”

+ +

“I’ll bear that in mind, too. Tell me, Cadfael,” said Hugh, eyeing him +shrewdly, “how strong is the scent you got wind of? Say I find no such +witness—no second such witness, ought I to say?—shall I be justified +in wagering on the accuracy of your nose?”

+ +

“In your shoes,” said Cadfael cheerfully, “I +would.”

+ +

“You seem to have found your witness in very short order,” remarked Hugh +drily, “and without leaving the precinct. So you got it out of him—whatever it +was that had him choking on a simple lie. I thought you would.” He rose, +grinning, and set down his cup. “I’ll take your confession later, I’m away now +to see what I can get out of the new wife.” He clouted Cadfael amiably on the +shoulder in passing, and looked back from the doorway. “No need to fret for +that weedy lad of yours, I’m coming round to your opinion. I doubt if he ever +did worse in his life than sneak a few apples from an orchard.”

+ +

The journeyman, Iestyn, was working alone in the shop, repairing the broken +clasp of a bracelet, when Hugh came to the Aurifaber burgage. It was the first +time Hugh had spoken with this man alone, and in company Iestyn kept himself +silent and apart. Either he was taciturn by nature, thought Hugh, or the family +had taken care to make his status clear to him, and it was not theirs, and +there should be no stepping over the line that divided them.

+ +

In answer to Hugh’s question he shook his head, smiling and hoisting +impassive shoulders.

+ +

“How would I see what goes on in the street after dark or who’s on the prowl +when decent folks are in bed? I sleep in the back part of the undercroft, +beneath the rear of the hall, my lord. Those outside stairs go down to my bed, +as far from the lane as you can get. I neither see nor hear anything from +there.”

+ +

Hugh had already noted the stairs that dived below the house at the rear, a +shallow flight, since the ground dropped steadily away from the street level, +and the undercroft, completely below-ground at the street end, was half +above-ground at the back. From there, certainly, a man would be cut off from +the world outside.

+ +

“At what hour did you go there, two nights ago?”

+ +

Iestyn knotted his thick black brows and considered. “I’m always early, +having to rise early. I reckon about eight that night, as soon as my supper had +settled.”

+ +

“You had no late errands to do? Nothing that took you out again after that?”

+ +

“No, my lord.”

+ +

“Tell me, Iestyn,” said Hugh on impulse, “are you content in your work here? +With Master Walter and his family? You have fair treatment, and a good +relationship?”

+ +

“One that suits me well enough,” said Iestyn cautiously. “My wants are +simple, I make no complaint. I never doubt time will bring me my due. First to +earn it.”

+ +

Susanna met Hugh in the hall doorway, and bade him in with the same +practical composure she would have used with any other. Questioned, she +shrugged away all knowledge with a rueful smile.

+ +

“My chamber is here, my lord, between hall and store, the length of the +house away from the street. Baldwin’s boy did not come to us with his trouble, +though he well could have done. At least he would have had company. But he +didn’t come, so we knew nothing of his master being still astray until the +morning, when John came. I was sorry poor Griffin worried out the night alone.”

+ +

“And you had not seen Master Peche during the day?”

+ +

“Not since morning, when we were all about the yard and the well. I went +across to his shop at dinner with a bowl of broth, having plenty to spare, and +it was then John told me he’d gone out. Gone since mid-morning and said +something about the fish rising. To the best I know, that’s the last known word +of him.”

+ +

“So Boneth has told me. And no report of him from any shop or ale-house or +friend’s house since. In a town where every man knows every man, that’s +strange. He steps over his door-sill and is gone.” He looked up the broad, +unguarded stairs that led up from beyond her door to the gallery and the rooms +above. “How are these chambers arranged? Who has the one on the street, above +the shop?”

+ +

“My father. But he sleeps heavily. Yet ask him, who knows but he may have +heard or seen something. Next to him my brother and his wife. Daniel is away to +Frankwell, but Margery you’ll find in the garden with my father. And then my +grandmother has the nearest chamber. She keeps her room today, she’s old and +has had some trying seizures, perilous at her age. But she’ll be pleased if you +care to visit her,” said Susanna, with a brief, flashing smile, “for all the +rest of us grow very tedious to her, she’s worn us out long ago, we no longer +amuse her. I doubt if she can tell you anything that will help you, my lord, +but the change would do marvels for her.”

+ +

She had wide eyes at once distant and brilliant, fringed with lashes russet +as her coil of lustrous hair. A pity there should be grey strands in the +russet, and fine wrinkles, whether of laughter or long-sighted pain, at the +corners of the grey eyes, and drawn lines, like cobweb, about her full, firm +mouth. She was, Hugh judged, at least six or seven years older than he, and +seemed more. A fine thing spoiled for want of a little spending. Hugh had come +by what was his as an only child, but he did not think a sister of his would +have been left thus used and unprovided, to furnish a brother richly forth.

+ +

“I’ll gladly present myself to Dame Juliana,” he said, “when I have spoken +with Master Walter and Mistress Margery.”

+ +

“That would be kind,” she said. “And I could bring you wine, and that would +give me the chance to bring her, with it, a dose she might otherwise refuse to +take, even though Brother Cadfael comes tomorrow and she minds him more than +any of us. Go down this way, then, my lord. I’ll look for you returning.”

+ +

Either the goldsmith had nothing to tell, or else could not bring himself to +spend even words. The one thing that haunted him day and night was his lost +treasury, of which he had rendered an inventory piece by piece, almost coin by +coin, in loving and grieving detail. The coins in particular were notable. He +had silver pieces from before Duke William ever became King William, fine +mintage not to be matched now. His father and grandfather, and perhaps one +progenitor more, must have been of the same mind as himself, and lived for +their fine-struck wealth. Walter’s head might be healed now without, but his +loss might well have done untold harm to the mind within.

+ +

Hugh stood patiently under the apple and pear trees of the orchard, pressing +his few questions concerning the vanishing of Baldwin Peche. Almost it seemed +to him that the name no longer struck any spark, that Walter had to blink and +shake himself and think hard before he could recall the name or the face of his +dead tenant. He could not see the one or remember the other for brooding on his +voided coffer.

+ +

One thing was certain, if he knew of anything that could help to recover his +goods, he would pour it out in a hurry. Another man’s death, by comparison, +meant little to him. Nor did it seem that he had yet hit upon one possibility +that was hovering in Hugh’s mind. If there was indeed a connection between the +robbery and this death, need it be the one to which the town had jumped so +nimbly? Robbers can also be robbed, and may even be killed in the robbing. +Baldwin Peche had been a guest at the wedding, he had made the locks and keys +for the strong-box, and who knew the house and shop better than he?

+ +

Margery had been feeding the fowls that scratched in an arrow run under the +town wall, at the bottom of the garden. Until a year previously Walter had even +kept his two horses here within the town, but recently he had acquired a +pasture and an old stable across the river, westward from Frankwell, where +Iestyn was regularly sent to see that they were fed and watered and groomed, +and exercise them if they were short of work. The girl was coming up the slope +of the garden with the morning’s eggs in a basket, the bulk of the wall in +shadow behind her, and the narrow door in it closed. A short, rounded, +insignificant young person to the view, with an untidy mass of fair hair. She +made Hugh a wary reverence, and raised to him a pair of round, unwavering eyes.

+ +

“My husband is out on an errand, sir, I’m sorry. In half an hour or so he +may be back.”

+ +

“No matter,” said Hugh truly, “I can speak with him later. And you may well +be able to speak for both, and save the time. You know on what business I’m +engaged. Master Peche’s death seems likely to prove no accident, and though he +was missing most of the day, yet the night is the most favourable time for +villainies such as murder. We need to know what every man was doing two nights +ago, and whether he saw or heard anything that may help us lay hands on the +culprit. I understand your chamber is the second one, back from the street, yet +you may have looked out and seen someone lurking in the alley between the +houses, or heard some sound that may have meant little to you then. Did you +so?”

+ +

She said at once: “No. It was a quiet night, like any other.”

+ +

“And your husband made no mention of noticing anything out of the way? No +one out and about on the roads when law-abiding people are fast at home? Had he +occasion to be in the shop late? Or any errand outside?”

+ +

Her rose and white countenance flushed very slowly a deeper rose, but her +eyes did not waver, and she found a ready excuse for her colour. “No, we +retired in good time. Your lordship will understand—we are only a few days +married.”

+ +

“I understand very well!” said Hugh heartily. “Then I need hardly ask you if +your husband so much as left your side.”

+ +

“Never for a moment,” she agreed, and voice and flush were eloquent, whether +they told truth or no.

+ +

“The idea would never have entered my mind,” Hugh assured her urbanely, “if +we had not the testimony of a witness who says he saw your husband creeping out +of the house and making off in haste about an hour after Compline that night. +But of course, more’s the unwisdom, not all witnesses tell the truth.”

+ +

He made her a civil bow, and turned and left her then, neither lingering nor +hurrying, and strolled back up the garden path to the house. Margery stood +staring after him with her underlip caught between her teeth, and the basket of +eggs dangling forgotten from her hand.

+ +

She was waiting and watching for Daniel when he came back from Frankwell. +She drew him aside into a corner of the yard, where they could not be +overheard, and the set of her chin and brows stopped his mouth when he began to +blurt out loud, incautious wonder at being thus waylaid. Instead, he questioned +in an uneasy undertone, impressed by her evident gravity: “What is it? What’s +the matter with you?”

+ +

“The sheriff’s deputy has been here asking questions. Of all of us!”

+ +

“Well, so he must, what is there in that? And what, of all people, could you +tell him?” The implied scorn did not escape her; that would change, and soon.

+ +

“I could have told what he asked me,” she spat, bitter and low, “where +you were all night on Monday. But could I? Do I even know? I know what I +believed then, but why should I go on believing it? A man who was out of his +bed and loose in the town that night may not have been bustling to another +woman’s bed after all—he could have been battering Baldwin Peche over +the head and throwing him into the river! That’s what they are +thinking. And now what am I to believe? Bad enough if you left me to go to that +woman while her husband’s away—oh, yes, I was there, do you remember when she +told you, all nods and winks, the shameless whore!—that he was bound away for +several days! But how do I know now that that’s what you were about?”

+ +

Daniel was gaping at her, white-faced and aghast, and gripping her hand as +if his senses at that moment had no other anchor. “Dear God, they can’t think +that! You can’t believe that of me? You know me better…”

+ +

“I don’t know you at all! You pay me no attention, you’re nothing but a +stranger to me, you steal out at night and leave me in tears, and what do you +care?”

+ +

“Oh, God!” babbled Daniel in a frantic whisper, “What am I to do? And you +told him? You told him I went out—the whole night?”

+ +

“No, I did not. I’m a loyal wife, if you’re no proper husband to me. I told +him you were with me, that you never left my side.”

+ +

Daniel drew breath deep, gawping at her in idiot relief, and began to smile, +and jerk out praise and thanks incoherently while he wrung her hand, but +Margery measured out her moment like a fencer, and struck the grin ruthlessly from +his face.

+ +

“But he knows it is not true.”

+ +

“What?” He collapsed again into terror. “But how can he? If you told him I +was with you…”

+ +

“I did. I’ve perjured myself for you and all to no purpose. I gave +nothing away, though God knows I owe you nothing. I put my soul in peril to +save you from trouble! And then he tells me smoothly that there’s a witness who +saw you sneak out that night and has the hour right, too, so never think this +was a trick. There is such a witness. You’re known to have been out +roving in the dark the night that man was murdered.”

+ +

“I never had ought to do with it,” he wailed softly. “I told you truth…”

+ +

“You told me you had things to do that were no concern of mine. And +everybody knows you had no love for the locksmith.”

+ +

“Oh, God!” moaned Daniel, gnawing his knuckles. “Why did I ever go near the +girl? I was mad! But I swear to you, Margery, that was all, it was to Cecily I +went… and never again, never! Oh, girl, help me… what am I to do?”

+ +

“There’s only one thing you can do,” she said forcefully. “If that’s truly +where you were, you must go to this woman, and get her to speak up for you, as +she ought. Surely she’ll tell the truth, for your sake, and then the sheriff’s +men will let you alone. And I’ll confess that I lied. I’ll say it was for shame +of being so slighted, though it was truly for love of you—however little you +deserve it.”

+ +

“I will!” breathed Daniel, weak with fear and hope and gratitude all +mingled, and stroking and caressing her hand as he had never done before. “I’ll +go to her and ask her. And never see her again, I promise you, I swear to you, +Margery.”

+ +

“Go after dinner,” said Margery, securely in the ascendancy, “for you must +come and eat and put a good face on it. You can, you must. No one else knows of +this, no one but I, and I’ll stand by you whatever it cost me.”

+ +

Mistress Cecily Corde did not brighten or bridle at the sight of her lover +creeping in at the back door of her house early in the afternoon. She scowled +as blackly as so golden a young woman could, hauled him hastily into a closed +chamber where they could not possible be overlooked by her maidservant, and +demanded of him, before he had even got his breath back, what he thought he was +doing there in broad daylight, and with the sheriff’s men about the town as +well as the usual loiterers and gossips. In a great, gasping outpour Daniel +told her what he was about, and why, and what he needed, entreated, must have +from her, avowal that he had spent Monday night with her from nine of the +evening until half an hour before dawn. His peace of mind, his safety, perhaps +his life, hung on her witness. She could not deny him, after all they had meant +to each other, all he had given her, all they had shared.

+ +

Once she had grasped what he was asking of her, Cecily disengaged violently +from the embrace she had permitted as soon as the door was closed, and heaved +him off in a passion of indignation.

+ +

“Are you mad? Throw my good name to the four winds to save your skin? I’ll +do no such thing, the very idea of asking it of me! You should be ashamed! +Tomorrow or the next day my man will be home, and very well you know it. You +would not have come near me now, if you had any thought for me. And like this, +in daylight, with the streets full! You’d better go, quickly, get away from +here.”

+ +

Daniel clung, aghast, unable to believe in such a reception. “Cecily, it may +be my life! I must tell them…”

+ +

“If you dare,” she hissed, backing violently out of his desperate attempt at +an embrace, “I shall deny it. I shall swear that you lie, that you’ve pestered +me, and I’ve never encouraged you. I mean it! Dare mention my name and I’ll +brand you liar, and bring witness enough to bear me out. Now go, go, I never +want to see you again!”

+ +

Daniel fled back to Margery. She had the shrewd sense to be watching for +him, having known very well what his reception must be, and spirited him +competently away to their own chamber where, if they kept their voices down, +they could not be heard. Dame Juliana, next door, slept in the afternoon and +slept soundly. Their private business was safe from her.

+ +

In agitated whispers he poured out everything though he was telling her +nothing she did not already know. She judged it time to soften against his +shoulder, while keeping the mastery firmly in her own hands. He had been +shocked out of his male complacency, and almost out of his skin, she felt pity +and affection for him, but that was a luxury she could not yet afford.

+ +

“Listen, we’ll go together. You have a confession to make, but so have I. +We’ll not wait for the Lord Beringar to come to us, we’ll go to him. I’ll own +that I lied to him, that you left me alone all that night, knowing you were +gone to a paramour. You’ll tell him the same. I shall not know her name. And +you will refuse to give it. You must say she is a married woman, and it would +be her ruin. He’ll respect you for it. And we’ll say that we start anew, from +this hour.”

+ +

She had him in her hand. He would go with her, he would swear to whatever +she said. They would start anew from that hour; and she would be holding the +reins.

+ +

In bed that night she clasped a devout, grateful husband, who could not fawn +on her enough. Whether Hugh Beringar had believed their testimony or not, he +had received it with gravity, and sent them away solemnly admonished but +feeling themselves delivered. A Daniel eased of all fear that the eye of the +law was turned ominously upon him would sit still where a hand could be laid on +him at any moment.

+ +

“It’s over,” Margery assured him, fast in his arms, and surprisingly +contented there, considering all things. “I’m sure you need not trouble any +more. No one believes you ever harmed the man. I’ll stand with you, and we have +nothing to fear.”

+ +

“Oh, Margery, what should I have done without you?” He was drifting +blissfully towards sleep, after extreme fear and the release of correspondingly +great pleasure. Never before had he felt such devotional fervour, even to his +mistresses. This might have been said to be his true wedding night. “You’re a +good girl, loyal and true…”

+ +

“I’m your wife, who loves you,” she said, and more than half believed it, to +her own mild surprise. “And loyal you’ll find me, whenever you call upon me. I +shall not fail you. But you must also stand by me, for as your wife I have +rights.” It was well to have him so complacent, but not to let him fall asleep, +not yet. She took steps to rouse him; she had learned a great deal in one +unsatisfactory week. While he was still glowing, she pursued very softly and +sweetly: “I am your wife now—wife to the heir, there’s a status belongs to me. +How can I live in a house and have no place, no duties that are mine by right?”

+ +

“Surely you have your place,” he protested tenderly. “The place of honour, +mistress of the house. What else? We all bear with my grandmother, she’s old +and set in her ways, but she doesn’t meddle with the housekeeping.”

+ +

“No, I don’t complain of her, of course we must reverence the elders. But +your wife should be granted her due in responsibilities as well as privilege. +If your mother still lived it would be different. But Dame Juliana has given up +her direction of the household, being so old, to our generation. I am sure your +sister has done her duty nobly by you all all these years…”

+ +

Daniel hugged her close, his thick curls against her brow. “Yes, so she has, +and you can keep your hands white and take your ease, and be the lady of the +house, why should you not?”

+ +

“That is not what I want,” said Margery firmly, gazing up into the dark with +wide-open eyes. “You’re a man, you don’t understand. Susanna works hard, no one +could complain of her, she keeps a good table without waste, and all the linen +and goods and provisions in fine order, I know. I give her all credit. But that +is the wife’s work, Daniel. Your mother, if she had lived. Your wife, +now you have a wife.”

+ +

“Love, why should you not work together? Half the load is lighter to bear, +and I don’t want my wife worn out with cares,” he murmured smugly into the +tangle of her hair. And thought himself very cunning, no doubt, wanting peace +as men always want it, far before justice or propriety; but she would not let +him get away with that sop.

+ +

“She won’t give up any part of the load, she has had her place so long, she +stands off any approach. Only on Monday I offered to fetch in the washing for +her, and she cut me off sharply, that she would do herself. Trust me, +my love, there cannot be two mistresses in one house, it never prospers. She +has the keys at her girdle, she sees the store-bins kept supplied, and +the linen mended and replaced, she gives the orders to the maid, she +chooses the meats and sees them cooked as she wishes. She +comes forth as hostess when visitors appear. All my rights, Daniel, +and I want them. It is not fitting that the wife should be so put aside. What +will our neighbours say of us?”

+ +

“Whatever you want,” he said with sleepy fervour, “you shall have. I do see +that my sister ought now to give up her office to you, and should have done so +willingly, of her own accord. But she has held the reins here so long, she has +not yet considered that I’m now a married man. Susanna is a sensible woman, +she’ll see reason.”

+ +

“It is not easy for a woman to give up her place,” Margery pointed out +sternly. “I shall need your support, for it’s your status as well as mine in +question. Promise me you will stand with me to get my rights.”

+ +

He promised readily, as he would have promised her anything that night. Of +the two of them, she had certainly been the greater gainer from the day’s +crises and recoveries. She fell asleep knowing it, and already marshalling her +skills to build on it.

+
+
+

Chapter Nine

+ +

« ^ »

+ +

Thursday: from morning to late evening

+ +

Dame Juliana +tapped her way down the broad wooden treads of the stairs to the hall in good +time on the following morning, determined to greet Brother Cadfael when he came +after breakfast with all the presence and assurance of a healthy old lady in +full command of her household, even if she had to prepare her seat and +surroundings in advance and keep her walking-stick handy. He knew that she was +no such matter, and she knew that he knew it. She had a foot in the grave, and +sometimes felt it sinking under her and drawing her in. But this was a final +game they played together, in respect and admiration if not in love or even liking.

+ +

Walter was off to his workshop with his son this morning. Juliana sat +enthroned in her corner by the stairs, cushioned against the wall, eyeing them +all, tolerant of all, content with none. Her long life, longer than any woman +should be called upon to sustain, trailed behind her like a heavy bridal train +dragging at the shoulders of a child bride, holding her back, weighing her +down, making every step a burden.

+ +

As soon as Rannilt had washed the few platters and set the bread-dough to +rise, she brought some sewing to a stool in the hall doorway, to have the full +light. A decent, drab brown gown, with a jagged tear above its hem. The girl +was making a neat job of mending it. Her eyes were young. Juliana’s were very +old, but one part of her that had not mouldered. She could see the very +stitches the maid put in, small and precise as they were.

+ +

“Susanna’s gown?” she said sharply. “How did she come to get a rent like +that? And the hems washed out too! In my day we made things last until they +wore thin as cobweb before we thought of discarding them. No such husbandry +these days. Rend and mend and throw away to the beggars! Spendthrifts all!”

+ +

Plainly nothing was going to be right for the old woman today, she was +determined to make her carping authority felt by everyone. It was better, on +such days, to say nothing, or if answers were demanded, make them as short and +submissive as possible.

+ +

Rannilt was glad when Brother Cadfael came in through the passage with +dressings in his scrip for the ulcer that was again threatening to erupt on the +old woman’s ankle. The thin, eroded skin parted at the least touch or graze. He +found his patient reared erect and still in her corner, waiting for him, silent +and thoughtful for once, but at his coming she roused herself to maintain, in +the presence of this friendly enemy, her reputation for tartness, obstinacy and +grim wit, and for taking always, with all her kin, the contrary way. Whoever +said black, Juliana would say white.

+ +

“You should keep this foot up,” said Cadfael, cleaning the small but ugly +lesion with a pad of linen, and applying a new dressing. “As you know very +well, and have been told all too often. I wonder if I should not rather be +telling you to stamp about upon it day-long—then you might do the opposite and +let it heal.”

+ +

“I kept my room yesterday,” she said shortly, “and am heartily sick of it +now. How do I know what they get up to behind my back while I’m shut away up +there? Here at least I can see what goes on and speak up if I see cause—as I +will, to the end of my days.”

+ +

“Small doubt!” agreed Cadfael, rolling his bandage over the wound and +finishing it neatly. “I’ve never known you baulk your fancy yet, and never +expect to. Now, how is it with your breathing? No more chest pains? No +giddiness?”

+ +

She would not have considered she had had her full dues unless she had +indulged a few sharp complaints of a pain here, or a cramp there, and she did +not grudge it that most of them he brushed away no less bluntly. It was all a +means of beguiling the endless hours of the day that seemed so long in passing, +but once past, rushed away out of mind like water slipping through the fingers.

+ +

Rannilt finished her mending, and carried off the gown into Susanna’s +chamber, to put it away in the press; and presently Susanna came in from the +kitchen and stopped to pass the time of day civilly with Cadfael, and enquire +of him how he thought the old woman did, and whether she should continue to +take the draught he had prescribed for her after her seizure.

+ +

They were thus occupied when Daniel and Margery came in together from the +shop. Side by side they entered, and there was something ceremonious in their +approach, particularly in their silence, where they had certainly been talking +together in low, intent tones on the threshold. They barely greeted Cadfael, +not with any incivility, but rather as if their minds were fixed on something +else, and their concentration on it must not be allowed to flag for a moment. +Cadfael caught the tension and so, he thought, did Juliana. Only Susanna seemed +to notice nothing strange, and did not stiffen in response.

+ +

The presence of someone not belonging to the clan was possibly an +inconvenience, but Margery did not intend to be deflected or to put off what +she was braced to say.

+ +

“We have been discussing matters, Daniel and I,” she announced, and for a +person who looked so soft and pliable her voice was remarkably firm and +resolute. “You’ll understand, Susanna, that with Daniel’s marriage there are +sure to be changes in the order here. You have borne the burden of the house +nobly all these years…” That was unwise, perhaps; it was all those years that +had dried and faded what must once have been close to beauty, their signature +was all too plain in Susanna’s face. “But now you can resign it and take your +leisure and no reproach to you, it’s well earned. I begin to know my way about +the house, I shall soon get used to the order of the day here, and I am ready +to take my proper place as Daniel’s wife. I think, and he thinks too, that I +should take charge of the keys now.”

+ +

The shock was absolute. Perhaps Margery had known that it would be. Every +trace of colour drained out of Susanna’s face, leaving her dull and opaque as +clay, and then as swiftly the burning red flooded back, rising into her very +brow. The wide grey eyes stared hard and flat as steel. For long moments she +did not speak; Cadfael thought she could not. He might have stolen silently +away and left them to their fight, if he had not been concerned for its +possible effect on Dame Juliana. She was sitting quite still and mute, but two +small, sharp points of high colour had appeared on her cheek bones, and her +eyes were unusually bright. Or again, he might in any case have stayed, +unobtrusive in the shadows, having more than his fair share of human curiosity.

+ +

Susanna had recovered her breath and the blood to man her tongue. Fire +kindled behind her eyes, like a vivid sunset through a pane of horn.

+ +

“You are very kind, sister, but I do not choose to quit my charge so +lightly. I have done nothing to be displaced, and I do not give way. Am I a +slave, to be put to work as long as I’m needed, and then thrown out at the +door? With nothing? Nothing! This house is my home, I have +kept it, I will keep it: my stores, my kitchen, my linen-presses, all +are mine. You are welcome here as my brother’s bride,” she said, +cooling formidably, “but you come new into an old rule, in which I +bear the keys.”

+ +

The quarrels of women are at all times liable to be bitter, ferocious and +waged without quarter, especially when they bear upon the matriarchal +prerogative. Yet Cadfael found it surprising that Susanna should have been so +shaken out of her normal daunting calm. Perhaps this challenge had come earlier +than she had expected, but surely she could have foreseen it and need not, for +that one long moment, have stood so mute and stricken. She was ablaze now, +claws bared and eyes sharp as daggers.

+ +

“I understand your reluctance,” said Margery, growing sweet as her opponent +grew bitter. “Never think there is any implied complaint, oh, no, I know you +have set me an exemplary excellence to match. But see, a wife without a +function is a vain thing, but a daughter who has borne her share of the burden +already may relinquish it with all honour, and leave it to younger hands. I +have been used to working, I cannot go idle. Daniel and I have talked this +over, and he agrees with me. It is my right!” If she did not nudge him in the +ribs, the effect was the same.

+ +

“So we have talked it over and I stand by Margery,” he said stoutly. “She is +my wife, it’s right she should have the managing of this house which will be +hers and mine. I’m my father’s heir, shop and business come to me, and this +household comes to Margery just as surely, and the sooner she can take it upon +her, the better for us all. Good God, sister, you must have known it. Why +should you object?”

+ +

“Why should I object? To be dismissed all in a moment like a thieving +servant? I, who have carried you all, fed you, mended for you, saved for you, +held up the house over you, if you had but the wit to know it or the grace to +admit it. And my thanks is to be shoved aside into a corner to moulder, is it, +or to fetch and carry and scrub and scour at the orders of a newcomer? No, that +I won’t do! Let your wife clerk and count for you, as she claims she did for her +father, and leave my stores, my kitchen, my keys to me. Do you think I’ll +surrender tamely the only reason for living left to me? This family has denied +me any other.”

+ +

Walter, if he had anticipated any of this, had been wise to keep well away +from it, safe in his shop. But the likelihood was that he had never been warned +or consulted, and was expendable until this dispute was settled.

+ +

“But you knew,” cried Daniel, impatiently brushing aside her lifelong +grievance, seldom if ever mentioned so plainly before, “you knew I should be +marrying, and surely you had the sense to know my wife would expect her proper +place in the house. You’ve had your day, you’ve no complaint. Of course the +wife has precedence and requires the keys. And shall have them, too!”

+ +

Susanna turned her shoulder on him and appealed with flashing eyes to her +grandmother, who had sat silent this while, but followed every word and every +look. Her face was grim and controlled as ever, but her breathing was rapid and +shallow, and Cadfael had closed his fingers on her wrist to feel the beat of +her blood there, but it remained firm and measured. Her thin grey lips were set +in a somewhat bitter smile.

+ +

“Madam grandmother, do you speak up! Your word still counts here as mine, it +seems, cannot. Have I been so useless to you that you, also, want to discard +me? Have I not done well by you all, all this while?”

+ +

“No one has found fault with you,” said Juliana shortly. “That is not the +issue. I doubt if this chit of Daniel’s can match you, or do the half as well, +but I suppose she has the goodwill and the perseverance to learn, if it has to +be by her errors. What she has, and so I tell you, girl, is the right of the +argument. The household rule is owing to her, and she will have to have it. I +can say no other, like it or lump it. You may as well make it short and final, +for it must happen.” And she rapped her stick sharply on the floor to make a +period to the judgement.

+ +

Susanna stood gnawing at her lips and looking from face to face of all these +three who were united against her. She was calm now, the anger that filled her +had cooled into bitter scorn.

+ +

“Very well,” she said abruptly. “Under protest I’ll do what’s required of +me. But not today. I have been the mistress here for years, I will not be +turned out in the middle of my day’s work, without time to make up my accounts. +She shall not be able to pick flies here and there, and say, this was left +unfinished, or, she never told me there was a new pan needed, or, here’s a +sheet was left wanting mending. No! Margery shall have a full inventory +tomorrow, when I’ll hand over my charge. She shall have it listed what stocks +she inherits, to the last salt fish in the last barrel. She shall start with a +fair, clean leaf before her. I have my pride, even if no other regards it.” She +turned fully to Margery, whose round fair face seemed distracted between +satisfied complacency and discomfort, as if she did not quite know, at this +moment, whether to be glad or sorry of her victory. “Tomorrow morning you shall +have the keys. Since the store-room is entered through my chamber, you may also +wish to have me move from there, and take that room yourself. Then you may. +From tomorrow I won’t stand in your way.”

+ +

She turned and walked away out of the hall door and round towards the kitchen, +and the bunch of keys at her waist rang as if she had deliberately set them +jangling in a last derisive spurt of defiance. She left a charged silence +behind her, which Juliana was the first one bold enough to break.

+ +

“Well, children, make yourselves content,” she said, eyeing her grandson and +his bride sardonically. “You have what you wanted, make the most of it. There’s +hard work and much thought goes into running a household.”

+ +

Margery hastened to ingratiate herself with thanks and promises. The old woman +listened tolerantly, but with that chill smile so unnervingly like Susanna’s +still on her lips. “There, be off now, and let Daniel get back to his work. +Brother Cadfael, I can see, is none too pleased with seeing me roused. I’m +likely to be getting some fresh potion poured into me to settle me down, +through the three of you and your squabbles.”

+ +

They went gladly enough, they had much to say to each other privately. +Cadfael saw the spreading grey pallor round Juliana’s mouth as soon as she +relaxed her obstinate self-control and lay back against her cushions. He +fetched water from the cooling jar, and shook out a dose of the powdered oak +mistletoe for her to take. She looked up at him over the cup with a sour grin.

+ +

“Well, say it! Tell me my granddaughter has been shabbily used!”

+ +

“There is no need for me to say it,” said Cadfael, standing back to study her +the better and finding her hands steady, her breath even, and her countenance +as hardy as ever, “since you know it yourself.”

+ +

“And too late to mend it. But I’ve allowed her the one day she wanted. I +could have denied her even that. When I gave her the keys, years ago, you don’t +think they were the only ones? What, leave myself unfurnished? No, I can still +poke into corners, if I choose. And I do, sometimes.”

+ +

Cadfael was packing his dressings and unguents back into his scrip, but with +an eye still intent on her. “And do you mean to give up both bunches to +Daniel’s wife now? If you had meant mischief, you could have handed them to her +before your granddaughter’s face.”

+ +

“My mischief is almost over,” said Juliana, suddenly sombre. “All keys will +be wrested from me soon, if I don’t give them up willingly. But these I’ll keep +yet a day or two. I still have a use for them.”

+ +

This was her house, her family. Whatever boiled within it, ripe for +eruption, was hers to deal with. No outsider need come near.

+ +

In the middle of the morning, when Susanna and Rannilt were both busy in the +kitchen, and would certainly be occupied for some time, and the men were at +work in the shop, Juliana sent the only remaining witness, Margery, to fetch +her a measure of a strong wine she favoured for mulling from a vintner’s a +satisfactory distance away across the town. When she had the hall to herself, +she rose, bearing down heavily on her stick, and felt beneath her full skirt +for the keys she kept hidden in a bag-pocket there.

+ +

Susanna’s chamber door was open. A narrow rear door gave quick access here +to the strip of yard which separated the kitchen from the house. Faintly +Juliana could hear the voices of the two women, their words indistinguishable, +their tones revealing. Susanna was cool, short and dry as always. The girl +sounded anxious, grieved, solicitous. Juliana knew well enough about that +truant day when the chit had come home hastily and in the dark. No one had told +her, but she knew. The sharpness of her senses neither denied nor spared her +anything. Shabbily used, and too late to mend! The girl had been listening, +appalled, to the quarrel in the hall, and felt for the mistress who had shown +her kindness. Young things are easily moved to generous indignation and +sympathy. The old have no such easy grace.

+ +

The store-room with its heavy vats of salted food, jars of oil, crocks of +flour and oatmeal and dry goods, tubs of fat, bunches of dried herbs, shared +the width of the hall with Susanna’s chamber, and opened out of it. This door +was locked. Juliana fitted the key Baldwin Peche had cut for her before ever +she gave up the original, and opened the door and went in, into the myriad fat, +spicy, aromatic, salt smells of the pantry.

+ +

She was within for perhaps ten minutes, hardly more. She was ensconced in +her cushioned corner under the staircase and the door locked again securely by +the time Margery came back with her wine, and the spices needed to mull it to +her liking for her indulgence at bedtime.

+ +

“I have been telling this youngster,” said Brother Anselm, fitting together +curved shards of wood with the adroit delicacy appropriate to the handling of +beloved flesh wounded, “that should he consider taking vows as a novice here, +his tenure would be assured. A life of dedication to the music of worship—what +better could he seek, gifted as he is? And the world would withdraw its hand from +him, and leave him in peace.”

+ +

Liliwin kept his fair head bent discreetly over the small mortar in which he +was industriously grinding resins for the precentor’s gum, and said never a +word, but the colour rose in his neck and mounted his cheek and brow to the +hair-line. What was offered might be a life secured and at peace, but it was +not the life he wanted. Whatever went on inside that vulnerable and anxious +head of his, there was not the ghost of a vocation for the monastic life there. +Even if he escaped his present peril, even if he won his Rannilt and took her away +with him, after more of the world’s battering he might end as a small vagrant rogue, +and she as what? His partner in some enforced thievery, picking pockets at fair +and market in order to keep them both alive? Or worse, as his breadwinner by +dubious means when all else failed? We have more to answer for here, thought +Brother Cadfael, watching the work in silence, than the rights and wrongs of +one local charge of robbery and assault. What we send out from here, in the +end, must be armed against fate in something better than motley.

+ +

“A fast learner, too,” said Anselm critically, “and very biddable.”

+ +

“Where he’s busy with what he loves, no doubt,” agreed Cadfael, and grinned +at seeing Liliwin’s brief, flashing glance, which met his eyes and instantly +avoided them, returning dutifully to the work in hand. “Try teaching him his +letters instead of the neums, and he may be less ardent.”

+ +

“No, you mistake, he has an appetite for either. I could teach him the +elements of Latin if I had him for one year.”

+ +

Liliwin kept his head down and his mouth shut, grateful enough, and from the +heart, for such praise, greedy to benefit by such generous teaching, enlarged +and comforted by such simple kindness, and desirous of gratifying his tutor in +return, if only he could. Now that his innocence began to be accepted as a +probability, however uncertain as yet, these good people began also to make +plans for his future. But his place was not here, but with his little dark +girl, wherever their joint wanderings might take them about the world. Either +that or out of the world, if the forty days of grace ebbed out without true +vindication.

+ +

When the light faded too far to allow the fine work to continue, Brother +Anselm bade him take the organetto and play and sing by ear to show off his +skills to Brother Cadfael. And when Liliwin somewhat forgot himself and +launched into a love song, innocent enough but disturbing within these walls, +Anselm showed no sign of perturbation, but praised the melody and the verses, +but the melody above all, and noted it down briskly to be translated to the +glory of God.

+ +

The Vesper bell silenced their private pleasure. Liliwin put away the +organetto with hasty gentleness, and followed to pluck Cadfael by the sleeve.

+ +

“Did you see her? Rannilt? She came to no harm by me?”

+ +

“I saw her. She was mending a gown, altogether composed and in no trouble. +You did her no harm. Yesterday, I hear, she was singing at her work.”

+ +

Liliwin released him with a thankful sigh and a whisper of gratitude for +such news. And Cadfael went in to Vespers reflecting that he had told but the +more welcome half of truth, and wondering if Rannilt felt much like singing +this evening. For she had overheard the battle that sent Susanna away defeated, +displaced, robbed of the only realm a parsimonious grandmother and sire had +left her. And Susanna was the mistress who, if she had never shown her much +warmth, had nevertheless kept her from cold, hunger and blows and, above all, +had sent her to her strange marriage, so heretically blessed, and witnessed only +by the saints whose relics sanctified her marriage bed. Tomorrow Susanna would +give up the keys of her realm to a young rival. The little Welsh girl had a +partisan heart, quicker to grief even than to joy. No, she would not feel like +singing until tomorrow was over.

+ +

Rannilt crouched unsleeping on her pallet in the kitchen until all the house +lights had been put out, except one, on which her attention was fixed. A +miserly household goes early to bed to save lights and fuel, banking down the +hearth-fire in the hall under small rubble, and snuffing all the candles and +lamps. It was barely Compline, only just dark, but the young pair, quite full +of each other now and cooing like doves, were happy enough to withdraw to their +bed, and the others habitually fell asleep with the sun and awoke with it. Only +in the store-room, showing a narrow chink of light downhill towards the +kitchen, was there a candle still burning.

+ +

Rannilt had taken off neither shoes nor gown, but sat hugging herself for +warmth and watching that meagre slit of light. When it was the only waking sign +remaining, she got up and stole out across the few yards of hard-stamped earth +between, and pressed herself against the narrow door that led into Susanna’s +chamber.

+ +

Her lady was there within awake, tireless, proud, going between her chamber +and the store, hard at work as she had sworn, resolute to render account of +every jar of honey, every grain of flour, every drop of oil or flake of fat. +Rannilt burned and bled for her, but also she went in awe of her, she dared not +go in and cry aloud her grief and indignation.

+ +

The steps that moved about within were soft, brisk and purposeful. All +Susanna’s movements were so, she did everything quickly, nothing in apparent +haste, but now it did seem to Rannilt’s anxious ear that there was something of +bridled desperation about the way she took those few sharp paces here and +there, about her last housewifely survey in this burgage. The slight went deep +with her, as well it might.

+ +

The faint gleam of light vanished from the slit window of the store-room, +and reappeared at the chink of the shutter of the bed-chamber. Rannilt heard +the door between closed, and the key turned in the lock. Even on this last +night Susanna would not sleep without first securing the safety of her charge. +But surely now she had finished, and would go to her bed and take what rest she +could.

+ +

The light went out. Rannilt froze into stillness in the listening silence, +and after a long moment heard the inner door into the hall opened.

+ +

On the instant there was a sharp, brief sound, a subdued cry that was barely +audible, but so charged with dismay and anger that Rannilt put a hand to the +latch of the door against which she stood pressed, half in the desire to hold +fast to something solid and familiar, half wishful to go in and see what could +have provoked so desolate and frustrated a sound. The door gave to her touch. +Distant within the hall she heard a voice, the words indistinguishable, but the +grim tones unmistakably those of Dame Juliana. And Susanna’s voice replying, +bitter and low. Two muted murmurs, full of resentment and conflict, but private +as pillow confidences between man and wife.

+ +

Trembling, Rannilt pushed open the door, and crept across towards the open +door into the hall, feeling her way in the dark. There was a feeble gleam of +light high within the hall, it seemed to her to be shining from the head of the +stairs. The old woman would not let anything happen in this house without +prying and scolding. As though she had not done enough already, discarding her +granddaughter and siding with the newcomer!

+ +

Susanna had half-closed the door of her room behind her, and Rannilt could +see only the shadowy outline of her left side, from shoulder to hems, where she +stood some three or four paces into the hall. But the voices had words now.

+ +

“Hush, speak low!” hissed the old woman, fiercely peremptory. “No need to +wake the sleepers. You and I are enough to be watching out the night.”

+ +

She must be standing at the head of the stairs, with her small night-lamp in +one hand and shielded by the other, Rannilt judged. She did not want to rouse +any other member of the household.

+ +

“One more, madam, than is needed!”

+ +

“Should I leave you lone to your task, and you still hard at work so late? +Such diligence! So strict in your accounting, and so careful in your providing!”

+ +

“Neither you nor she, grandmother, shall be able to claim that I left one +measure of flour or one drop of honey unaccounted for,” said Susanna bitingly.

+ +

“Nor one grain of oatmeal?” there was a small, almost stealthy quiver of +laughter from the head of the stairs. “Excellent housewifery, my girl, to find +your crock still above half-full, and Easter already past! I give you your due, +you have managed your affairs well.”

+ +

“I learned from you, grandmother.” Susanna had vanished from the chink of +the door, taking a step towards the foot of the staircase. It seemed to Rannilt +that she was now standing quite still, looking up at the old woman above her, +and spitting her soft, bitter protest directly into the ancient face peering +down at her in the dimness. What light the small lamp gave cast her shadow +along the boards of the floor, a wide black barrier across the doorway. By the +shape of the shadow, Susanna had wrapped her cloak about her, as well she +might, working late in the chill of the night. “It is at your orders, +grandmother,” she said, low and clearly, “that I am surrendering my affairs. +What did you mean to do with me now? Had you still a place prepared for me? A +nunnery, perhaps?”

+ +

The shadow across the doorway was suddenly convulsed, as though she had +flung out her arms and spread the cloak wide.

+ +

After those bitterly discreet exchanges the screech that tore the silence +was so terrifying that Rannilt forgot herself, and started forward, hurling the +inner door wide and bursting into the hall. She saw Dame Juliana, at the head +of the stairs, shaken and convulsed as the black shadow had been, the lamp +tilting and dripping oil in her left hand, her right clutching and clawing at +her breast. The mouth that had just uttered that dreadful shriek was wrenched +side long, the cheek above drawn out of shape. All this Rannilt saw in one +brief glimpse, before the old woman lurched forward and fell headlong down the +stairs, to crash to the floor below, and the lamp, flying from her hand, spat a +jet of burning oil along the boards at Susanna’s feet, and went out.

+
+
+

Chapter Ten

+ +

« ^ »

+ +

Thursday night to Friday dawn

+ +

Rannilt sprang +to smother the little serpent of fire that had caught something burnable and +sent up a spurt of flame. Blindly, fumbling, her hands found the hard corner of +a cloth-wrapped bundle, there on the floor near the wall, and beat out the fire +that had caught at the fraying end of the cord that bound it. A few sparks +floated and found splinters of wood, and she followed on her knees and quenched +them with the hem of her skirt, and then it was quite dark. Not for long, for +everyone in the house must be awake now; but for this moment, utterly dark. +Rannilt groped about her blindly on the floor, trying to find where the old +woman lay.

+ +

“Stay still,” said Susanna, in the gloom behind her. “I’ll make light.”

+ +

She was gone, quick and competent again as ever, back into her own room, +where she could lay her hands instantly on flint and tinder, always ready by +her bed. She came with a candle, and lit the oil-lamp in its bracket on the +wall. Rannilt got up from her knees and darted to where Juliana lay on her face +at the foot of the stairs. But Susanna was before her, kneeling beside her +grandmother and running rapid hands over her in search of broken bones from her +fall, before venturing to lift her over on to her back. Old bones are brittle, +but it had not been a sheer fall, rather a rolling tumble from stair to stair.

+ +

Then they were all coming, clutching candles, gaping, crying questions, +Daniel and Margery with one gown thrown hastily round the two of them, Walter +bleared and querulous with sleep, Iestyn scurrying up the outdoor stairs from +the undercroft and in by the rear door of Susanna’s chamber, which Rannilt had +left standing open. Light on light sprang up, the usual frugal rule forgotten.

+ +

They came crowding, demanding, incoherent with sleep, and alarm and +bewilderment. The smoky flames and flickering shadows filled the hall with +changing shapes that danced about the two figures quiet on the floorboards. +What had happened? What was all the noise? What was the old woman doing out of +her bed? Why the smell of burning? Who had done this?

+ +

Susanna slid an arm under her grandmother’s body, cradled the grey head with +her other palm, and turned her face-upward. She cast up at the clamouring +circle of her kin one cold, glittering glance in which Rannilt saw, as none of +them did, the scorn in which she held all members of her family but this spent +and broken one on her arm.

+ +

“Hold your noise, and make yourselves useful. Can you not see? She came out +with her light to see how I was fairing, and she took another seizure like the +last, and fell, and the last it may very well be. Rannilt can tell you. Rannilt +saw her fall.”

+ +

“I did,” said Rannilt, quivering. “She dropped the lamp and caught at her +breast, and then she fell. The oil spilled and took fire, I put it out…” She +looked towards the wall for the bundle, whatever it had been, that had offered +an end of tow to the spark, but there was nothing there now. “She’s not dead… +look, she’s breathing… Listen!”

+ +

Certainly she was, for as soon as they hushed their clamour the air shook to +her shallow-drawn, rattling breath. All one side of her face was dragged askew, +the mouth grossly twisted, the eyes half-open and glaring whitely; and all her +body on that side lay stiff as a board, the fingers of her hand contorted and +rigid.

+ +

Susanna looked round them all, and made her dispositions, and no one now +challenged her right. “Father, and Daniel, carry her to her bed. She has no +broken bones, she feels nothing. We cannot give her any of her draught, she +could not swallow it. Margery, feed the little brazier in her room. I will get +wine to mull for when she revives—if she does revive.”

+ +

She looked over Rannilt’s shoulder to Iestyn, standing dumb and at a loss in +the shadows. Her face was set as marble and as cold, but her eyes shone clear. +“Run to the abbey,” she said. “Ask for Brother Cadfael to come to her. +Sometimes he works late, if he has medicines making. But even if he has gone to +his cell, the porter will call him. He said he would come if he was needed. He +is needed now.”

+ +

Iestyn looked back at her without a word, and then turned as silently as he +had come and ran as she had bade him.

+ +

It was not so late as all that. At the abbey the dortoir was still half +awake, an uneasy stirring in certain cells, where the brothers found sleep +difficult or remembrance all too strong. Brother Cadfael, having stayed late in +his workshop to pound herbs for a decoction to be made next day, was just at +his private prayers before sleep when the porter came edging along the passage +between the cells to find him. He rose at once, and went silently down the +night stairs and through the church, to confer with the messenger at the +gatehouse.

+ +

“The old dame, is it?” He had no need to fetch anything from the herbarium, +the best of what he could give her was already supplied and Susanna knew how to +use it, if its use was still of any avail. “We’d best hurry, then, if it’s so +grave.”

+ +

He set a sharp pace along the Foregate and over the bridge, and asked such +questions as were necessary as they went.

+ +

“How did she come to be up and active at this hour? And how did this fit come +on?”

+ +

Iestyn kept station at his side and answered shortly. He had never many +words to spare. “Mistress Susanna was up late seeing to her stores, for she’s +forced to give up her keys. And Dame Juliana rose up, belike, to see what she +was still about. The fit took her at the top of the stairs and she fell.”

+ +

“But the seizure came first? And caused the fall?”

+ +

“So the women say.”

+ +

“The women?”

+ +

“The maid was there and saw it.”

+ +

“What’s her state now, then? The old dame? Has she bones broken? Can she +move freely?”

+ +

“The mistress says nothing broken, but one side of her stiff as a tree, and +her face drawn all on a skew.”

+ +

They were let in at the town gate without question. Cadfael occasionally had +much later errands and was well known. They climbed the steep curve of the Wyle +in silence, the gradient making demands on their breath.

+ +

“I warned her the last time,” said Cadfael, when the slope eased, “that if +she did not keep her rages in check the next fit might be the last. She was +well in command of herself and all about her this morning, for all the mischief +that was brewing in the house, but I had my doubts… What can have upset her +tonight?”

+ +

But if Iestyn had any answer to that, he kept it to himself. A taciturn man, +who did his work and kept his own counsel.

+ +

Walter was hopping about uneasily at the entrance to the passage, watching +for them with a horn lantern in his hand. Daniel was huddled into his gown in +the hall, with the spendthrift candles still burning unheeded around him, until +Walter entered with the newcomers, and having seen them within, suddenly became +aware of gross waste, and begun to go round and pinch out two out of three, +leaving the smell of their hot wicks on the air.

+ +

“We carried her up to bed,” said Daniel, restless and wretched in this +upheaval that disrupted his new content. “The women are there with her. Go up, +they’re anxious for you.” And he followed, drawn to a trouble that must be +resolved before he could take any comfort, and hovered in the doorway of the +sick-chamber, but did not step within, Iestyn remained at the foot of the +stairs. In all the years of service here, most likely, he had never climbed +them.

+ +

A brazier burned in an iron basket set upon a wide stone, and a small lamp +on a shelf jutting out from the wall. Here in the upper rooms there were no +ceilings, the rooms went up into the vault of the roof, dark wood on all sides +and above. On one side of the narrow bed Margery, mute and pale, drew hastily +back into the shadows to let Brother Cadfael come close. On the other, Susanna +stood erect and still, and her head turned only momentarily to ascertain who it +was who came.

+ +

Cadfael sank to his knees beside the bed. Juliana was alive, and if one +sense had been snatched from her, the others she still had, at least for a +brief while. In the contorted face the ancient eyes were alive, alert and +resigned. They met Cadfael’s and knew him. The grimace could almost have been +her old, sour smile. “Send Daniel for her priest,” said Cadfael after one look +at her, and without conceal. “His errand here is more now than mine.” She would +appreciate that. She knew she was dying.

+ +

He looked up at Susanna. No question now who held the mastery here; no +matter how they tore each other, she of all these was Juliana’s blood, kin and +match. “Has she spoken?”

+ +

“No. Not a word.” Yes, she even looked as this woman must have looked fifty +years ago as a comely, resolute, able matron, married to a man of lesser fibre +than her own. Her voice was low, steady and cool. She had done what could be +done for the dying woman, and stood waiting for whatever broken words might +fall from that broken mouth. She even leaned to wipe away the spittle that ran +from its deformed lips at the downward corner.

+ +

“Have the priest come, for I am none. She is already promised our prayers, +that she knows.” And that was for her, to ensure that she was alive within this +dead body, and need not regret all her gifts to the abbey, doled out so +watchfully. Her faded eyes had still a flash within them; she understood. +Wherever she was gone, she knew what was said and done about her. But she had +said no word, nor even attempted speech.

+ +

Margery had stolen thankfully out of the room, to send her husband for the +priest. She did not come back. Walter was below, pinching out candles and +fretting over the few that must remain. Only Cadfael on one side of the bed and +Susanna on the other kept watch still by Dame Juliana’s death.

+ +

The old woman’s live eyes in her dead carcase clung to Cadfael’s face, yet +not, he thought, trying to convey to him anything but her defiant reliance on +her own resources. When had she not been mistress of her own household? And +these were still her family, no business of any other judge. Those outside must +stay outside. This monk whom she had grown to respect and value, for all their +differences, she admitted halfway, close enough to know and acknowledge her +rights of possession. Her twisted mouth suddenly worked, emitted an audible +sound, looked for a moment like a mouth that might speak memorable things. +Cadfael stooped his ear close to her lips.

+ +

A laborious murmur, indistinguishable, and then: “It was I bred them…” she +said thickly, and again struggled with incommunicable thoughts, and rested with +a rattling sigh. A tremor passed through her rigid body. A thread of utterance +emerged almost clearly: “But for all that… I should have liked to hold… my +great-grandchild…”

+ +

Cadfael had barely raised his head when she closed her eyes. No question but +it was by her will they closed, no crippling weakness. But for the priest, she +had done.

+ +

Even with the priest she did not speak again. She bore with his urgings, and +made the effort to respond with her eyelids when he made his required probings +into her sense of sin and need and hope for absolution. She died as soon as he +had pronounced it, or only moments later.

+ +

Susanna stood by her to the end and never uttered a word. When all was done, +she stooped and kissed the leather cheek and chilling brow somewhat better than +dutifully, and still with that face of marble calm. Then she went down to see +Brother Cadfael courteously out of the house, and thank him for all his +attentions to the dead.

+ +

“She gave you, I know, more work than ever she repaid you for,” said +Susanna, with the slight, bitter curl to her lips and the wry serenity in her +voice.

+ +

“And is it you who tell me so?” he said, and watched the hollows at the +corners of her lips deepen. “I came to have a certain reverence for her, short +of affection. Not that she ever required that of me. And you?”

+ +

Susanna stepped from the bottom stair, close to where Rannilt huddled +against the wall, afraid to trespass, unwilling to abandon her devoted watch. +Since Susanna had emerged from her room with the light, her cloak shed within +now there was work to do, Rannilt had hovered attentive, waiting to be used.

+ +

“I doubt,” said Brother Cadfael, considering, “whether there was any here +who loved her half so well as you.”

+ +

“Or hated her half so well,” said Susanna, lifting her head with one +measured flash of grey eyes.

+ +

“The two are often bed-fellows,” he said, unperturbed. “You need not +question either.”

+ +

“I will not. Now I must go back to her. She is my charge, I’ll pay her +what’s due.” She looked round and said quite gently: “Rannilt, take Master +Walter’s lantern, and light Brother Cadfael out. Then go to your bed, there is +no more for you to do here.”

+ +

“I’d rather stay and watch with you,” said Rannilt timidly. “You’ll need hot +water and cloths, and a hand to lift her, and to run errands for you.” As if +there were not enough of them, up there now about the bed, son, grandson, and +grandson’s woman, and how much grief among the lot of them? For Dame Juliana +had outstayed her time by a number of years and was one mouth less to feed once +her burial was accomplished; not to speak of the whiplash tongue and the +too-sharp eye removed from vexing.

+ +

“So you may, then,” said Susanna, gazing long upon the small, childlike +figure regarding her with great eyes from the shadows, where Walter had +quenched all but one candle, but inadvertently left his lantern burning. “You +shall sleep tomorrow in the day, you’ll be ready then for your bed and your +mind quiet. Come up, when you’ve shown Brother Cadfael out to the lane. You and +I will care for her together.”

+ +

“You were there?” asked Cadfael mildly, walking on the girl’s heels along +the pitch-dark passage. “You saw what happened?”

+ +

“Yes, sir. I couldn’t sleep. You were there this morning when they all +turned against her, and even the old woman said she must yield her place… You +know…”

+ +

“I know, yes. And you were aggrieved for her.”

+ +

“She—was never unkind to me…” How was it possible to say that Susanna had +been kind, where the chill forbade any such word? “It was not fair that they +should turn and elbow her out, like that.”

+ +

“And you were watching and listening, and grieving. And you went in. When +was that?”

+ +

She told him, as plainly as if she lived it again. She told him, as far as +she could recall it, and that was almost word for word, what she had heard pass +between grandmother and grandchild, and how she had heard the shriek that +heralded the old woman’s seizure, and burst in to see her panting and swaying +and clutching her bosom, the lamp tilting out of her hand, before she rolled +headlong down the stairs.

+ +

“And there was no other soul stirring then? No one within hand’s-touch of +her, there above?”

+ +

“Oh no, no one. She dropped the lamp just as she fell.” The little snake of +fire, spitting sparks and sudden leaping flame as it found the end of tow, +seemed to Rannilt to have nothing to do with what had happened. “And then it +was dark, and the mistress said keep still, and went for a light.”

+ +

Certain, then, yes quite certain she fell. No one was there to help her +fall, the only witnesses were below. And if they had not gone to her aid at +once, and sent as promptly for him, he would never have arrived here in time to +see Dame Juliana die. Let alone hear the only words she had spoken before dying. +For what they were worth! “I bred them all… For all that, I should have liked +to hold my great-grandchild…”

+ +

Well, her grandson, the only being she was reported to dote upon, was now a +husband, her proud old mind might well strain forward to embrace a future +generation.

+ +

“No, don’t come out into the lane, child, time for you to be withindoors, +and I know my way.”

+ +

She went, shy, wild and silent. And Cadfael made his way back thoughtfully +to his own cell in the dortoir and took what comfort he might, and what +enlightenment, but it was not much. In this death, at least, there was no +question of foul play. Juliana had fallen when no other person was near by, and +in an unquestionable seizure such as she had suffered twice before. The +dissensions within the house, moreover, had broken out in a disturbing form +that same day, cause enough for an old woman’s body and heart and irascible +nature to fail her. The wonder was this had not happened earlier. Yet for all +he could do, Cadfael’s mind could not separate this death from the first, nor +that from the felony of which Liliwin stood accused. There was, there must be, +a thread that linked them all together. Not by freakish chance was an ordinary +burgess household thus suddenly stricken with blow after blow. A human hand had +set off the chain; from that act all these later events stemmed, and where the +impetus would finally run out and the sequence of fatalities end was a +speculation that kept Cadfael awake half the night.

+ +

  + +In Dame Juliana’s death chamber the single lamp burned, a steady eye of +fire, at the head of the bed. The night hung deep and silent over the town, +past the mid-point between dusk and dawn. On a stool on one side Susanna sat, +her own hands folded in her lap, quiet at last. Rannilt crouched at the foot of +the bed, very weary but unwilling to go to her humble place, and certain that +sleep would not come to her if she did. The lofty timbers of the roof soared +above them into deep darkness. The three women, two living and one dead, were +drawn together into a close, mute intimacy, for these few hours islanded from +the world.

+ +

Juliana lay straight and austere, her grey hair combed into smooth order, +her face uncovered, the sheet folded at her chin. Already the contortion was +beginning to ease out of her features, and leave her at peace.

+ +

Neither of the two who watched beside her had spoken a word since their work +was finished. Susanna had made no bones about dismissing Margery’s reluctant +offer of help, and had no difficulty in getting rid of all three of her kin. +They were not sorry to return to their beds and leave all to her. Mistress and +maid had the vigil to themselves.

+ +

“You’re cold,” said Rannilt, breaking the silence very softly as she saw +Susanna shiver. “Shall I fetch up your cloak? You felt the want of it even +about the store, when you were on the move, and now we sit here, and the night +chiller than then. I’ll creep down for it.”

+ +

“No,” said Susanna absently. “It was a goose walking over my grave. I’m warm +enough.” She turned her head and gave the girl a long, sombre stare. “Were you +so vexed for me that you must wake and watch into the night with me? I thought +you came very quickly. Did you see and hear all?”

+ +

Rannilt trembled at the thought of having intruded uninvited, but Susanna’s +voice was equable and her face calm. “No. I wasn’t listening, but some part I +couldn’t help hearing. She praised your providing. Perhaps she was sorry then… +It was strange she should take to thinking on such things, and suddenly take +pride that you should still have the oatmeal crock above half-full… That I +heard. Surely she was sorry in the end that you should be so misprised. She +thought better of you than of any other.”

+ +

“She was returning to the days when she ruled all,” said Susanna, “and had +all on her shoulders, as I have had. The old go back, before the end.” Her +eyes, large and intent upon Rannilt’s face, gleamed in the dim, reflected light +from the lamp. “You’ve burned your hand,” she said. “I’m sorry.”

+ +

“It’s nothing,” said Rannilt, removing her hands hurriedly from sight into +her lap. “I was clumsy. The tow flared. It doesn’t hurt.”

+ +

“The tow…?”

+ +

“Tied round the bundle that was lying there. It had a frayed end and took +the flame before I was aware.”

+ +

“A pity!” said Susanna, and sat silent for some moments, watching her +grandmother’s dead face. The corners of her lips curved briefly in what hardly +had time to become a smile. “There was a bundle there, was there? And I was +wearing my cloak… yes! You noticed much, considering the fright we must have +given you, between us.”

+ +

In the prolonged silence Rannilt watched her lady’s face and went in great +awe, having trodden where she had no right to go, and feeling herself detected +in a trespass she had never intended.

+ +

“And now you are wondering what was in that bundle, and where it vanished to +before ever we began lighting candles. Along with my cloak!” Susanna fixed her +austere, half-smiling regard upon Rannilt’s daunted face. “It is only natural +you should wonder.”

+ +

“Are you angry with me?” ventured Rannilt in a whisper.

+ +

“No. Why should I be angry? I believe, I do believe, you have sometimes felt +for me as a woman for a woman. Is that true, Rannilt?”

+ +

“This morning…” faltered Rannilt, half-afraid, “I could not choose but +grieve…”

+ +

“I know. You have seen how I am despised here.” She went very gently and +quietly, a woman speaking with a child, but a child whose understanding she +valued. “How I have always been despised. My mother died, my grandmother grew +old, I was of value until my brother should take a wife. Yes, but barely a day +longer. All those years gone for nothing, and I am left here husbandless and +barren and out of office.”

+ +

There was another silence, for though Rannilt felt her breast bursting with +indignant sympathy, her tongue was frozen into silence. In the lofty darkness +of the roof-beams the faint, soft light quivered in a passing draught.

+ +

“Rannilt,” said Susanna gravely and softly, “can you keep a secret?”

+ +

“Your secret I surely can,” whispered Rannilt.

+ +

“Swear never to breathe a word to any other, and I’ll tell you what no one +else knows.”

+ +

Rannilt breathed her vow devotedly, flattered and warmed at having such +trust placed in her.

+ +

“And will you help me in what I mean to undertake? For I should welcome your +help… I need your help!”

+ +

“I’ll do anything in my power for you.” No one had ever expected or required +of her such loyalty, no one had ever considered her as better than menial and +impotent, no wonder her heart responded.

+ +

“I believe and trust you.” Susanna leaned forward into the light. “My bundle +and my cloak I made away out of sight before I brought the candle, and hid them +in my bedchamber. Tonight, Rannilt, but for this mortal stay, I meant to leave +this place, to quit this house that has never done me right, and this town in +which I have no honourable place. Tonight God prevented. But tomorrow night… +tomorrow night I am going! If you will help me I can take with me more of my +poor possessions than I can carry the first short piece of the way alone. Come +nearer, child, and I’ll tell you.” Her voice was very low and soft, a confiding +breath in Rannilt’s ear. “Across the bridge, at my father’s stable beyond +Frankwell, someone who sets a truer value on me will be waiting…”

+
+
+

Chapter Eleven

+ +

« ^ »

+ +

Friday: from morning to late evening

+ +

Susanna came +to the table as the subdued household assembled next morning, with the keys at +her girdle, and with deliberation unfastened the fine chain that held them, and +laid them before Margery.

+ +

“These are now yours, sister, as you wished. From today the management of +this house belongs to you, and I will not meddle.”

+ +

She was pale and heavy-eyed from a sleepless night, though none of them were +in much better case. They would all be glad to make an early night of it as +soon as the day’s light failed, to make up for lost rest.

+ +

“I’ll come round kitchen and store with you this morning, and show you what +you have in hand, and the linen, and everything I’m handing over to you. And I +wish you well,” she said.

+ +

Margery was almost out of countenance at such magnanimity, and took pains to +be conciliatory as she was conducted remorselessly round her new domain.

+ +

“And now,” said Susanna, shaking off that duty briskly from her shoulders, “I +must go and bring Martin Bellecote to see about her coffin, and father will be +off to visit the priest at Saint Mary’s. But then—you’ll hold me excused—I +should like to get a little sleep, and so must the girl there, for neither of +us has closed an eye.”

+ +

“I’ll manage well enough alone,” said Margery, “and take care not to disturb +you in that chamber for today. If I may take out what’s needed for the dinner now, +then you can get your rest.” She was torn between humility and exultation. +Having death in the house was no pleasure, but the gloom would lie heavy for +only a few days, and then she was rid of all barriers to her own plans, free of +the old, censorious eyes watching and disparaging her best efforts, free of +this ageing virgin, who would surely absent herself from all participation in +the running of the house hereafter, and mistress of a tamed husband who would +dance henceforth to her piping.

+ +

  + +Brother Cadfael spent the early part of that afternoon in the herb-garden, +and having seen everything left in order there, went out to view the work along +the Gaye. The weather continued sunny and warm, and the urchins of the town and +the Foregate, born and bred by the water and swimmers almost before they could +walk, were in and out of the shallows, and the bolder and stronger among them +even venturing across where the Severn ran smoothly. The spring spate from the +mountains was over now, the river showed a bland face, but these water-children +knew its tricks, and seldom trusted it too far.

+ +

Cadfael walked through the flowering orchard, very uneasy in his mind after +the night’s alarms, and continued downstream until he stood somewhere opposite +the gardens of the burgages along the approach to the castle. Halfway up the +slope the tall stone barrier of the town wall crossed, its crest crumbled into +disrepair in places, not yet restored after the rigours of the siege two years +ago. Within his vision it was pierced by two narrow, arched doorways, easily +barred in dangerous times. One of the two must be in the Aurifaber grounds, but +he could not be sure which. Below the wall the greensward shone fresh and +vivid, and the trees were in pale young leaf and snowy flower. The alders leaned +over the shallows lissome and rosy with catkins. Willow withies shone gold and +silver with the fur-soft flowers. So sweet and hopeful a time to be threatening +a poor young man with hanging or bludgeoning a single household with loss and +death.

+ +

The boys of the Foregate and the boys of the town were rivals by tradition, +earring into casual warfare the strong local feeling of their sires. Their +water-games sometimes became rough, though seldom dangerous, and if one rash +spirit overstepped the mark, there was usually an older and wiser ally close +by, to clout him off and haul his victim to safety. There was some horse-play +going on in the shallows opposite as Cadfael watched. An imp of the Foregate +had ventured the crossing, plunged into a frolic of town children before they +were aware, and ducked one of them spluttering below the surface. The whole +incensed rout closed on him and pursued him some way downstream, until he +splashed ashore up a slope of grass to escape them, falling flat in the +shallows in his haste, and clawing and scrambling clear in a flurry of spray. +From a smooth greensward where he certainly had no right to be, he capered and +crowed at them as they drew off and abandoned the chase.

+ +

It seemed that he had fished something up with him out of the shallow water +and gravel under the bushes. He sat down and scrubbed at it in his palm, intent +and curious. He was still busy with it when another boy hardly older than +himself came naked out of the orchard above, dropping his shirt into the grass, +and trotting down towards the water. He saw the intruder, and checked at gaze, +staring.

+ +

The distance was not so great but Cadfael knew him, and knew, in +consequence, at whose extended burgage he was looking. Thirteen years old, +well-grown and personable; Baldwin Peche’s simpleton boy, Griffin, let loose +from his labours for an hour to run down through the wicket in the wall, and +swim in the river like other boys.

+ +

Griffin had seen, far better than Cadfael across the river could hope to +see, whatever manner of trophy the impudent invader from the Foregate had +discovered in the shallows. He let out an indignant cry, and came running down +the grass to snatch at the cupped hand. Something dropped, briefly glinting, +into the turf, and Griffin fell upon it like a hawk swooping and caught it up +jealously. The other boy, startled, leaped to his feet and made to grab at it +in his turn, but gave back before a taller challenger. He was not greatly +disturbed at losing his toy. There was some exchange, light-hearted on his side, +slow and sober on Griffin’s. The two youthful voices floated light, excited +sounds across the water. The Foregate urchin shrilled some parting insult, +dancing backwards towards the river, jumped in with a deliberate splash, and +struck out for his home waters, sudden and silvery as a trout.

+ +

Cadfael moved alertly to where the child must come ashore, but kept one eye +on the slope opposite also, and saw how Griffin, instead of plunging in after +his repulsed rival, went back to lay his trophy carefully in the folds of the +shirt he had discarded by the bushes. Then he slid down the bank and waded out +into the water, and lay facedown upon the current in so expert and easy a +fashion that it was plain he had been a swimmer from infancy. He was rolling +and playing in the eddies when the other boy hauled himself ashore into the +grass of Cadfael’s bank, shedding water and glowing from his play, and began to +caper and clap his arms about his slender body in the sunny air. Grown men +would hardly be trying that water for a month or so yet, but the young have +energy enough to keep them warm, and as old men tend to say tolerantly, where +there’s no sense there’s no feeling.

+ +

“Well, troutling,” said Cadfael, knowing this imp as soon as he drew close, +“what was that you fished out of the mud over yonder? I saw you take to the +land. Not many yards ahead of the vengeance, either! You picked the wrong +haven.”

+ +

The boy had aimed expertly for the place where he had left his clothes. He +darted for his cotte, and slung it round his nakedness, grinning. “I’m not +afeared of all the town hobbledehoys. Nor of that big booby of the locksmith’s, +neither, but he’s welcome to his bit of trumpery. Knew it for his master’s, he +said! Just a little round piece, with a man’s head on it with a beard and a +pointed hat. Nothing to fall out over.”

+ +

“Besides that Griffin is bigger than you,” said Cadfael innocently.

+ +

The imp made a scornful face, and having scrubbed his feet and ankles +through the soft grass, and slapped his thighs dry, set to work to wriggle into +his hose. “But slow, and hasn’t all his wits. What was the thing doing drifted +under the gravel in the water there, if there was any good in it? He can have +it for me!”

+ +

And he was off at an energetic run to rejoin his friends, leaving Cadfael +very thoughtful. A coin silted into the gravel under the bank there, where the +river made a shallow cove, and clawed up in the fist of a scrambling urchin who +happened to sprawl on his face there in evading pursuit. Nothing so very +strange in that. All manner of things might turn up in the waters of Severn, +queerer things than a lost coin. All that made it notable was that this one +should turn up in that particular place. Too many cobweb threads were tangling +around the Aurifaber burgage, nothing that occurred there could any longer be +taken as ordinary or happening by chance. And what to make of all these +unrelated strands was more than Cadfael could yet see.

+ +

He went back to his seedlings, which at least were innocent of any mystery, +and worked out the rest of the afternoon until it drew near the time to return +for Vespers; but there was still a good half-hour in hand when he was hailed +from the river, and looked round to see Madog rowing upstream, and crossing the +main current to come to shore where Cadfael was standing. He had abandoned his +coracle for a light skiff, quite capable, as Cadfael reflected with a sudden +inspiration, of ferrying an inquisitive brother across to take a look for himself +at that placid inlet where the boy had dredged up the coin of which he thought +so poorly.

+ +

Madog brought his boat alongside, and held it by an oar dug into the soft +turf of the bank. “Well, Brother Cadfael, I hear the old dame’s gone, then. +Trouble broods round that house. They tell me you were there to see her set +out.”

+ +

Cadfael owned it. “After fourscore years I wonder if death should be +accounted troublous. But yes, she’s gone. Before midnight she left them.” +Whether with a blessing or a curse, or only a grim assertion of her dominance +over them and defence of them, loved or unloved, was something he had been +debating in his own mind. For she could have spoken, but had said only what she +thought fit to say, nothing to the point. The disputes of the day, surely +relevant, she had put clean away. They were her people. Whatever needed +judgement and penance among them was her business, no concern of the world +outside. And yet those few enigmatic words she had deliberately let him hear. +Him, her opponent, physician and—was friend too strong a word? To her priest +she had responded only with the suggested movements of her eyelids saying yea +and nay, confessing to frailties, agreeing to penitence, desiring absolution. But +no words.

+ +

“Left them at odds,” said Madog shrewdly, his seamed oak face breaking into +a wry smile. “When have they been anything else? Avarice is a destroying thing, +Cadfael, and she bred them all in her own shape, all get and precious little +give.”

+ +

“I bred them all,” she had said, as though she admitted a guilt to which her +eyelids had said neither yea nor nay for the priest.

+ +

“Madog,” said Cadfael, “row me over to the bank under their garden, and as +we go I’ll tell you why. They hold the strip outside the wall down to the +waterside. I’d be glad to have a look there.”

+ +

“Willingly!” Madog drew the skiff close. “For I’ve been up and down this +river from the water-gate, where Peche kept his boat, trying to find any man +who can give me word of seeing it or him after the morning of last Monday, and +never a glimpse anywhere. And I doubt Hugh Beringar has done better enquiring +in the town after every fellow who knew the locksmith, and every tavern he ever +entered. Come inboard, then, and sit yourself down steady, she rides a bit +deeper and clumsier with two aboard.”

+ +

Cadfael slid down the overhanging slope of grass, stepped nimbly upon the +thwart, and sat. Madog thrust off and turned into the current. “Tell, then! +What is there over there to draw you?”

+ +

Cadfael told him what he had witnessed, and in the telling it did not seem +much. But Madog listened attentively enough, one eye on the surface eddies of +the river, running bland and playful now, the other, as it seemed, on some +inward vision of the Aurifaber household from old matriarch to new bride.

+ +

“So that’s what’s caught your fancy! Well, whatever it may mean, here’s the +place. That Foregate lad left his marks, look where he hauled his toes up after +him, and the turf so moist and tender.”

+ +

A quiet and almost private place it was, once the skiff was drawn in until +its shallow draught gravelled. A little inlet where the water lay placid, clean +speckled gravel under it, and even in that clear bottom the boy’s clutching +hands had left small indentations. Out of one of those hollows—the right hand, +Cadfael recalled—the small coin had come, and he had brought it ashore with him +to examine at leisure. Withies of both willow and alder grew out from the very +edge of the water on either side of the plane of grass which opened out above +into a broad green slope, steep enough to drain readily, smooth enough to +provide an airy cushion for bleaching linen. Only from across the river could +this ground be viewed, on this town shore it was screened both ways by the +bushes. Clean, washed, white pebbles, some of considerable size, had been piled +inshore of the bushes for weighting down the linens spread here to dry on +washing days when the weather was favourable. Cadfael eyed them and noted the +one larger stone, certainly fallen from the town wall, which had not their +water-smoothed polish, but showed sharp corners and clots of mortar still +adhering. Left here as it had rolled from the crest, perhaps used sometimes for +tying up boats in the shallows.

+ +

“D’you see ought of use to you?” asked Madog, holding his skiff motionless +with an oar braced into the gravel. The boy Griffin had long since enjoyed his +bathe, dried and clothed himself, and carried away his reclaimed coin to the +locksmith’s shop where John Boneth now presided. He had known John for a long +time as second only to his master; for him John was now his master in +succession.

+ +

“All too much!” said Cadfael.

+ +

There were the boy’s traces, clutching hands under the clear water, +scrabbling toes above in the grass. Down here he had found his trophy, above he +had sat to burnish and examine it, and had it snatched from him by Griffin. Who +knew it as his master’s, and was honest as only the simple can be. Here all +round the boat the withies crowded, there above in the sward lay the pile of +heavy pebbles and the fallen stone. Here swaying alongside danced the little +rafts of water-crowfoot, under the leaning alders. And most ominous of all, +here in the sloping grass verge, within reach of his hand, not one, but three +small heads of reddish purple blossoms stood up bravely in the grass, the +fox-stones for which they had hunted in vain downstream.

+ +

The piled pebbles and the one rough stone meant nothing as yet to Madog, but +the little spires of purple blossoms certainly held his eyes. He looked from +them to Cadfael’s face, and back to the sparkling shallow where a man could not +well drown, if he was in his senses.

+ +

“Is this the place?”

+ +

The fragile, shivering white rafts of crowfoot danced under the alders, +delicately anchored. The little grooves left by the boy’s fingers very +gradually shifted and filled, the motes of sand and gravel sliding down in the +quiver of water to fill them. “Here at the foot of their own land?” said Madog, +shaking his head. “Is it certain? I’ve found no other place where this third +witness joins the other two.”

+ +

“Under the certainty of Heaven,” said Cadfael soberly, “nothing is ever +quite certain, but this is as near as a man can aim. Had he stolen and been +found out? Or had he found out too much about the one who had stolen, +and was fool enough to let it be known what he knew? God sort all! Ferry me +back now, Madog, I must hurry back to Vespers.”

+ +

Madog took him, unquestioning, except that he kept his deep-browed and +sharp-sighted old eyes fixed on Cadfael’s face all the way across to the Gaye.

+ +

“You’re going now to render account to Hugh Beringar at the castle?” asked +Cadfael.

+ +

“At his own house, rather. Though I doubt if he’ll be there yet to expect +me.”

+ +

“Tell him all that we have seen there,” said Cadfael very earnestly. “Let +him look for himself, and make what he can of it. Tell him of the coin—for so I +am sure it was—that was dredged up out of the cove there, and how Griffin +claimed it for his master’s property. Let Hugh question him on that.”

+ +

“I’ll tell him all,” said Madog, “and more than I understand.”

+ +

“Or I, either, as yet. But ask him, if his time serves for it, to come down +and speak with me, when he has made what he may of all this coil. For I shall +be worrying from this moment at the same tangle and may, who knows?—God +aiding!—may arrive at some understanding before night.”

+ +

  + +Hugh came late home from his dogged enquiries round the town which had +brought him no new knowledge, unless their cumulative effect turned probability +into certainty, and it could now be called knowledge that no one, in his +familiar haunts or out of them, had set eyes on Baldwin Peche since Monday noon. News of Dame Juliana’s death added nothing, she being so old, and yet there was +always the uncomfortable feeling that misfortune could not of itself have +concentrated such a volley of malice against one household. What Madog had to +tell him powerfully augmented this pervading unease.

+ +

“There within call of his own shop? Is it possible? And all present, the +alders, the crowfoot, the purple flower… Everything comes back, everything +comes home, to that burgage. Begin wherever we may, we end there.”

+ +

“That is truth,” said Madog. “And Brother Cadfael is cudgelling his wits +over the same tangle, and would be glad to consider it along with you, my lord, +if you can spare him the needed hour tonight, however late.”

+ +

“I’ll do that thankfully,” said Hugh, “for God knows it wants more cunning +that I have alone, and sharper vision, to see through this murk. Do you go home +and get your rest, Madog, for you’ve done well by us. And I’ll go knock up +Peche’s lad, and have out of him whatever he can tell us about this coin he +claims for his master’s.”

+ +

By this same hour Brother Cadfael had eased his own mind by imparting, after +supper, all that he had discovered to Abbot Radulfus, who received it with +thoughtful gravity.

+ +

“And you have sent word already to Hugh Beringar? You think he may wish to take +counsel with you further in the matter?” He was well aware that there was a +particular understanding between them, originating in events before he himself +took office at Shrewsbury. “You may take whatever time you need if he comes +tonight. Certainly this affair must be concluded as soon as possible, and it +does increasingly appear that our guest in sanctuary may have very little to do +with any of these offences. He is within here, but the evil continues without. If +he is innocent of all, in justice that must be shown to the world.”

+ +

Cadfael left the abbot’s lodging with time still for hard thought, and the +twilight just falling. He went faithfully to Compline and then, turning his +back on the dortoir, went out to the porch where Liliwin spread his blankets +and made his bed. The young man was still wide awake, sitting with his knees +drawn up and his back braced comfortably into the corner of the stone bench, a +small, hunched shadow in the darkness, singing over to himself the air of a +song he was making and had not yet completed to his satisfaction. He broke off +when Cadfael appeared, and made room beside him on his blankets.

+ +

“A good tune, that,” said Cadfael, settling himself with a sigh. “Yours? +You’d best keep it to yourself, or Anselm will be stealing it for the ground of +a Mass.”

+ +

“It is not ready yet,” said Liliwin. “There lacks a proper soft fall for the +ending. It is a love song for Rannilt.” He turned his head to look his companion +earnestly in the eyes. “I do love her. I’ll brave it out here and hang +rather than go elsewhere without her.”

+ +

“She would hardly be grateful to you for that,” said Cadfael. “But God +willing you shall not have to make any such choice.” The boy himself, though he +still went in suspense and some fear, was well aware that every day now cast +further doubt upon the case against him. “Things move there without, if in +impenetrable ways. To tell truth, the law is coming round very sensibly to my +opinion of you.”

+ +

“Well, maybe… But what if they found that I did leave here that night? They +wouldn’t believe my story as you did…” He cast a doubtful glance at Brother +Cadfael, and saw something in the bland stare that met him that caused him to +demand in alarm: “You haven’t told the sheriff’s deputy? You promised… for +Rannilt’s sake…”

+ +

“Never fret, Rannilt’s good name is as safe with Hugh Beringar as with me. +He has not even called on her as a witness for you, nor will not unless the +affair goes to the length of trial. Tell him? Well, so I did, but only after he +had made it plain he guessed the half. His nose for a reluctant liar is at +least as keen as mine, he never believed that ‘No’ he wrung out of you. So the +rest of it he wrung out of me. He found you more convincing telling truth than +lying. And then there is always Rannilt, if ever you need her witness, and the +watchmen who saw you pass in and out. No need to trouble too much about your +doings that night. I wish I knew as much about everyone else’s.” He pondered, +conscious of Liliwin’s intent and trusting regard. “There’s nothing more you’ve +recalled? The smallest detail concerning that house may be of help.”

+ +

Hesitantly Liliwin cast his mind back, and told over again the brief story +of his connection with the goldsmith’s house. The host at a tavern where he had +played and sung for his supper had told him of the marriage to be celebrated +next day, he had gone there hopefully, and been engaged for the occasion, he +had done his best to earn his money and been cast out, and hunted as a thief +and murderer here into the church. All of it known already.

+ +

“How much of that burgage did you ever see? For you went first in daylight.”

+ +

“I went to the shop and they sent me in through the passage to the hall +door, to the women. It was they who hired me, the old woman and the young one.”

+ +

“And in the evening?”

+ +

“Why, as soon as I came there they sent me to eat with Rannilt in the +kitchen, and I was there with her until they sent out for me to come and play +and sing while they feasted, and afterwards I played for dancing, and did my +acrobatics, and juggled—and you know how it ended.”

+ +

“So you never saw more than the passage and the yard. You never were down +the length of the garden, or through the town wall there to the waterside?”

+ +

Liliwin shook his head firmly. “I didn’t even know it went beyond the wall +until the day Rannilt came here. I could see as far as the wall when I went +through to the hall in the morning, but I thought it ended there. It was +Rannilt told me the drying-ground was beyond there. It was their washing day, +you see, she’d done all the scrubbing and rinsing, and had it all ready to go +out by mid-morning. But usually she has the dinner to prepare as well, and +watches the weather, and fetches the clothes in before evening. But that day +Mistress Susanna had said she would see to everything, and let Rannilt come +here to visit me. That was truly kind!”

+ +

Strange how sitting here listening to the boy’s recollections brought up +clearly the picture of that drying-ground he had never seen but through +Rannilt’s eyes, the slope of grass, the pebbles for anchors, the alders +screening the riverside, the town wall shielding the sward from the north and +leaving it open to the south…

+ +

“And I remember she said Mistress Susanna had her shoes and the hems of her +skirts wet when she came in from putting out the washing and found Rannilt +crying. But still she took note first for my girl being so sad… Never mind my +wet feet, she said, what of your wet eyes? Rannilt told me so!”

+ +

All ready to go out by mid-morning… As Baldwin Peche had gone out in +mid-morning for the last time. The fish rising… Cadfael, away pursuing his own +thoughts, suddenly baulked, realising, belatedly, what he had heard.

+ +

“What was that you said? She had her feet and skirts wet?”

+ +

“The river was a little high then,” explained Liliwin, undisturbed. “She’d +slipped on the smooth grass into the shallows. Hanging out a shirt on the +alders…”

+ +

And she came in calmly, and sent the maidservant away so that none other but +herself should go to bring in the linen. What other reason would any have for +passing through the wicket in the wall? And only yesterday Rannilt had been +sitting in the doorway to have the light on her work, mending a rent in the +skirt of a gown. And the brown at the hem had been mottled and faded, leaving a +tide-mark of dark colour round the pallor…

+ +

“Brother Cadfael,” called the porter softly from the archway into the +cloister, “Hugh Beringar is here for you. He said you would be expecting him.”

+ +

“I am expecting him,” said Cadfael, recalling himself with an effort from +the Aurifaber hall. “Bid him come through here. I think we have word for each +other.”

+ +

It was not quite dark, the sky being so clear, and Hugh knew his way +everywhere within these walls. He came briskly, made no objection to Liliwin’s +presence, and sat down at once in the porch to show the silver coin in his +palm.

+ +

“I’ve already viewed it in a better light. It’s a silver penny of the +sainted Edward, king before the Normans came, a beautiful piece minted in this +town. The moneyer was one Godesbrond, there are a few of his pieces to be +found, but few indeed in the town where they were struck. Aurifaber’s inventory +listed three such. And this was stuck between the boards of the bucket in their +well the morning after the theft. A scrap of coarse blue cloth, the lad says, +was caught in with it, but he thought nothing of that. But it seems to me that +whoever emptied Aurifaber’s coffer tipped all into a blue cloth bag and dropped +it into that bucket—the work of a mere few moments—to be retrieved later at +leisure in the dark hours, before the earliest riser went to draw water.”

+ +

“And whoever hoisted it out again,” said Cadfael, “snagged a corner of the +bag on a splinter… a small tear, just enough to let through one of the smaller +coins. It could be so. And Peche’s boy had found this?”

+ +

“He was the earliest riser. He went to draw water and lit on this. +He took it to his master, and was rewarded, and told not to let it out to any +other ears that the locksmith possessed any such. A great value, Peche said, he +set on this.”

+ +

So he well might, if it meant to him that someone there in that very +household must be the thief, and could be milked of the half of his gains in +return for silence. The fish were rising! Now Cadfael began gradually to +comprehend all that had happened. He forgot the young man hugging his knees and +stretching his amazed ears in the corner of the bench close to them. Hugh had +hardly given the boy a thought, so silent and so still he was.

+ +

“I think,” said Cadfael, picking his way without too much haste, for there +might yet be pitfalls, “that when he saw this he knew, or could divine with +very fair certainty, which of that household must be the robber. He foresaw +good pickings. What would he ask? A half-share in the booty? But it would not +have made any difference had he been far more modest than that, for the one he +approached had the force and the passion and the ruthlessness to act at once +and waste no time on parley. Listen to me, Hugh, and remember that night. They +sought Master Walter, found him stunned in his shop, and carried him up to his bed. +And then someone—no one seems certain who—cried that it must be the jongleur who +had done this, and sent the whole mob haring out after him, as we here +witnessed. Who, then, was left there to tend the stricken man, and the old +woman threatened by her fit?”

+ +

“The women,” said Hugh.

+ +

“The women. Of whom the bride was left to care for the victims upstairs in +their own chambers. It was Susanna who ran for the physician. Very well, so she +did. But did she run for him at once, or take but a few moments to run first to +the well and place what she found there in safer hiding?”

+ +

In a brief and awed silence they sat staring at each other.

+ +

“Is it possible?” said Hugh marvelling. “His daughter?”

+ +

“Among humankind all things are possible. Consider! This locksmith had the key +to the mystery put into his hands. If he had been honest he would have gone +straight to Walter or to Daniel and showed it, and told what he knew. He did +not, for he was not honest. He meant to gain by what he had found out. If he +did not approach the one he believed guilty until the Monday, it was because he +had no chance until then of doing so in private. He was as able as we to +remember how all the menfolk had gone baying after Liliwin here, and to reason +that it was a woman who reclaimed the treasury from the well and put it safely +away until all the hue and cry should be over, and a stray lad, with luck, +hanged for the deed. And who kept the keys of the house and had the best +command over all its hiding-places? He chose Susanna. And on Monday his time +came, when she took her basket of linen and went down through the wall to +spread it out in the drying-ground. About mid-morning Baldwin Peche was last +seen in his shop, and went off with some remark about the fish rising. No one +saw him, living, ever again.”

+ +

Liliwin, hitherto mute in his corner, leaned forward with a soft, protesting +cry: “You can’t mean it! She… But she was the only one, the only one who showed +Rannilt some kindness. She let her come to me for her comfort… She did not +truly believe that I…” He saw in time where he was headed, and halted +with a great groan.

+ +

“She had good reason to know that you never harmed her father’s +person or stole his goods. The best! And a sound reason, also, for sending +Rannilt away out of the house so that she herself, and none but she, should +fetch in the washing, or have any other occasion to go down to the riverside, +where she had left the extortioner dead.”

+ +

“I cannot believe,” whispered Liliwin, shaking, “that she could, even if she +would, do such a thing. A woman… kill?”

+ +

“You underrate Susanna,” said Cadfael grimly. “So did all her kin. And women +have killed, many a time.”

+ +

“Granted, then, that he followed her down to the river,” said Hugh. “You had +better go on. Tell us what you believe happened there, and how this thing came +about.”

+ +

“I think he came down after her to the brink, showed her the coin, and +demanded a share in her gains to pay for his silence. I think he, of all +people, had worst underestimated her. A mere woman! He expected prevarication, +lies, delay, perhaps pleading, some labour to convince her he knew what he knew +and meant what he said. He had greatly mistaken her. He had not bargained for a +woman who could accept danger instantly, with no outcry, make up her mind, and +act, stamping out the threat as soon as it arose. I think she spoke him fair +while she went on laying out the washing, and as he stood by the water’s edge +with the coin in his hand she so arranged that she passed behind him with a +stone in her hand, reaching to a corner of linen, and struck him down.”

+ +

“Go on,” said Hugh, “you cannot leave it there. There was more done than +that.”

+ +

“I think you already know. Whether the blow quite stunned him or not, it +flung him face-down into the shallow water. I think she did not wait to give +him time to recover his wits and try to rise, but went on acting instantly. Her +skirt and shoes were wet! I have only just learned it. And remember the bruises +on his back. I think she stepped upon him in the water, almost as he fell, and +held him down until he was dead.”

+ +

Hugh sat silent. It was Liliwin who uttered a small whimper of horror at +hearing it, and shook as if the night had turned cold.

+ +

“And then considered calmly the possibility that the river might find force +enough to float him away, and took steps to pin him down where he was, under +the alders, under the water, until he could be conveyed away by night, to be +discovered elsewhere, a drowned man. Do you recall the pitted bruise on his +shoulders? There is a jagged stone fallen from the town wall, beside the +pebbles there. As for the coin, it was under his body, she did not try to +recover it.”

+ +

Hugh drew deep breath. “It could be so! But it was not she who +followed her father to his shop and struck him down, for she is one person who is +vouched for fully, all that time that he was gone, until she went to look for +him. And then she cried out at once for help. There was no time at all when she +could have struck the blow or made off with the booty. She may have removed it +from the well later, she certainly did not put it there. You are arguing, I +take it, that there were two who planned this between them?”

+ +

“Two are implied. One to strike and steal and hide, the other to retrieve +the goods by night and secrete them in a safer place. One to destroy the +extortioner as soon as he declared himself, and the other to take away the body +and dispose of it by night. Yes, surely two.”

+ +

“Then who is the second? Certainly brother and sister who suffered from such +parsimonious elders might compound together to get their hands on what was +withheld from them, and certainly Daniel was abroad that night and furtive +about it. And for all his tale of a married woman’s bed rings likely enough, I +have still had an eye on him. Even shallow men can learn to lie.”

+ +

“I have not forgotten Daniel. But you may, for of all men living, her +brother is the least likely to have had any part in Susanna’s plans.” Cadfael +was recalling, as in a storm-flash of illumination, small, unremarkable, +unremarked things, Rannilt repeating the words she had overheard, Juliana’s +improbable praise of her granddaughter’s excellent housewifery, in preserving +her oatmeal crock half-full past Easter, and Susanna’s bitter taunt: “Had you +still a place prepared for me? A nunnery, perhaps?” And then the old woman +shrieked and fell down…

+ +

No, wait! There was more to it, he saw it now. The old woman at the head of +the stairs, the only light that of the little lamp she carried, a falling +light, pricking Susanna’s form and features into sharpest light and shade, +every curve or hollow magnified… Yes! She saw what she saw, she shrieked and +clutched her breast, and then fell, letting fall the revealing lamp from her +hand. Somehow she had known the half of it, and come forth by night to confront +her only, her best antagonist. She, too, must have seen the torn skirt, the +stained hem, and made her own connections. And she had still, she had said, a +use for those concealed keys of hers before she surrendered them at last. Yes, +and the last words she ever spoke: “For all that, I should have liked to hold +my great-grandchild…” Words better understood now than when first he had heard +them.

+ +

“No, now I see! Nothing now could have held her back. The man who compounded +with her to steal was no kinsman, nor one they would ever have admitted as kin. +They made their plans perforce, those two, to vanish from here together at the +first favourable time, and make a life somewhere far away from this town. Her +father grudged her a dowry, she has taken it for her herself. Whatever his name +may be, this man, we know now what he is. He is her lover. More, he is +the man who has got her with child.”

+
+
+

Chapter Twelve

+ +

« ^ »

+ +

Friday: night

+ +

Hugh was +on his feet before the last words were spoken. “If you’re right, after what has +happened they won’t wait for a better time. They’ve left it late as it is and +so, by God, have I.”

+ +

“You’re going there now? I am coming with you.” Cadfael was not quite easy +about Rannilt. In all innocence she had spoken out things that meant nothing +evil to her, but might uncover much evil to those who listened. Far better to +have her away before she could further threaten Susanna’s purposes. And it +seemed that the same fear had fallen upon Liliwin, for he scrambled hastily out +of the shadows to catch at Hugh’s arm before they could leave the cloister.

+ +

“Sir, am I free now? I need not hide here any longer? Then take me with you! +I want to fetch my girl away out of that house. I want her with me. How if they +take fright at her too much knowledge? How if they do her harm? I’m coming to +bring her away, whether or no it’s safe for me!”

+ +

Hugh clapped him heartily on the shoulder. “Come, and welcome. Free as a +bird, and I’ll ensure my men shall know it and hold you safe enough. Tomorrow +the town shall know it, too.”

+ +

There were no lights in the Aurifaber house when Hugh’s sergeant hammered at +the hall door. The household was already abed, and it took some time to rouse +any of the family. No doubt Dame Juliana, by this time, was shrouded and ready +for her coffin.

+ +

It was Margery who at last came down to enquire quaveringly through the +closed door who was without, and what was the matter at this time of night. At +Hugh’s order she opened and let them in, herself surprised and vexed that +Susanna, who slept downstairs, had not saved her the trouble. But it soon +became clear that Susanna was not there to hear any knocking. Her room was empty, +the bed undisturbed, the chest that had held her clothes now contained only a +few discarded and well-worn garments.

+ +

The arrival of the sheriff’s deputy and others, with several officers of the +law, very soon brought out all the inhabitants, Walter coming down blear-eyed +and suspicious, Daniel hurrying solicitously to his wife’s side, the boy Griffin +peering uncertainly from the other side of the yard. A curiously shrunken and +unimpressive gathering, without its two dominant members, and every one of +these few who remained utterly at a loss, staring about and at one another in +consternation, as though somewhere among the shadows of the hall they might +still discover Susanna.

+ +

“My daughter?” croaked Walter, looking about him helplessly. “But is she not +here? She must be… she was here as always, she put out the lights as she always +does, the last to her bed. Not an hour since! She cannot be gone!”

+ +

But she was gone. And so, as Cadfael found when he took a lantern and +slipped away by the outdoor stairs at the rear of the house and into the +undercroft, was Iestyn. Iestyn the Welshman, without money or family or +standing, who would never for a moment have been considered as fit for his +master’s daughter, even now she had ceased to be necessary to the running of +his master’s house, and was of no further value.

+ +

The undercroft ran under stone-vaulted ceilings the length of the house. On +impulse Cadfael left the cold, abandoned bed, and lit himself through to the +front, where a narrow stair ran up to a door into the shop. Directly opposite +to him, as he opened it, stood the pillaged coffer where Walter had kept his +wealth. There had been no shadow that night, no sound, only the candle had +flickered as the door was silently opened.

+ +

A few yards away, when Cadfael retraced his steps and again climbed the +outdoor stair, lay the well. And on his right hand, the door into Susanna’s +chamber, by which she could pass quickly between hall and kitchen, and a young +man from below-stairs could as well enter when all was dark.

+ +

They were gone, as they had surely planned to go one night earlier and been +detained by death. Acting on another thought, Cadfael went in by Susanna’s +door, and asked Margery to open for him the locked door of the store. The big +stone crock in which Susanna had kept her stock of oatmeal stood in one corner. +Cadfael lifted the lid, and held his lantern over it. There was still a +respectable quantity of grain left in the bottom of it, enough to hide quite a +large bundle, suitably disposed, but bereft of that padding it showed much less +than a quarter full. Juliana with her keys had been before him, and left what +she found there, intending, as always, to manage the fortunes of her own clan +with no interference from any other. She had known, and she had held her peace +when she could have spoken. And that stark girl, her nearest kin, all +desperation and all iron calm, had tended her scrupulously, and waited to learn +her fate without fear or complaint. The one as strong as the other, for good or +for evil, neither giving nor asking quarter.

+ +

Cadfael replaced the lid, went out and relocked the door. In the hall they +were fluttering and bleating, anxious to insist on their own innocence and +respectability at all costs, distracted at the thought that a kinswoman should +be suspect of such an enormity as robbing her own family. Walter stammered out +his answers, aghast at such treachery, almost incoherent with grief for his +lost money, lost to his own child. Hugh turned rather to Daniel.

+ +

“If she intended a long journey tonight, to take her out of our writ, or at +least out of our hold, where would she run? They would need horses. Have you +horses they may have taken?”

+ +

“Not here in the town,” said Daniel, pale-faced and tousled from bed, his +comeliness looking almost idiot at this pass, “but over the river we have a +pasture and a stable. Father keeps two horses there.”

+ +

“Which way? In Frankwell?”

+ +

“Through Frankwell and along the westward road.”

+ +

“And the westward road may well be our road,” said Cadfael, coming in from +the store, “for there’s a Welshman missing from under here, and what little he +had gone with him, and once well into Wales he can thumb his nose at the +sheriff of Shropshire. Whatever he may have taken with him.”

+ +

He had barely got it out, to indignant and disbelieving protests from +Walter, outraged at the mere suggestion of such a depraved alliance, when +Liliwin came bursting in from the rear quarters, his small person stiff and +quivering with alarm.

+ +

“I’ve been to the kitchen—Rannilt is not there. Her bed’s cold, she’s left +her things just as they are, nothing taken.” How little she must have to take, +but he knew the value, to one with virtually nothing, of the poor possessions +she had left behind. “They’ve taken her with them—they’re afraid of what she +knows and may tell. That woman has taken her,” he cried, challenging the +household, the law and all; “and she has killed and will kill again if she sees +need. Where will they have gone? For I am going after them!”

+ +

“So are we all,” said Hugh, and turned on Walter Aurifaber. Let the father +sweat for his own, as the lover did for his love. For his own by blood or by +greed. “You, sir, come with us. You say she had but an hour’s start of us and +on foot. Come, then, let’s be after them mounted. I sent for horses from the +castle, they’ll be in the lane by now. You best know the way to your own +stable, bring us there fast.”

+ +

The night was dark, clear and still young, so that light lingered in +unexpected places, won from a smooth plane of the river, a house-front of pale +stone, a flowering bush, or scattered stars of windflowers under the trees. The +two women had passed through the Welsh gate and over the bridge without +question. Owain Gwynedd, the formidable lord of much of Wales, withheld his +hand courteously from interfering in England’s fratricidal war, and very +cannily looked after his own interests, host to whoever fled his enemy, friend +to whoever brought him useful information. The borders of Shrewsbury he did not +threaten. He had far more to gain by holding aloof. But his own firm border he +maintained with every severity. It was a good night, and a good time of night, +for fugitives to ride to the west, if their tribal references were good.

+ +

Through the dark streets of the suburb of Frankwell they passed like +shadows, and Susanna turned westward, keeping the river still in view, along a +path between fields. The smaller bundle, but the heavier, Susanna carried. The +large and unwieldy one that held all her good clothes they carried between +them. It would have been too clumsy for one to manage alone. If I had not your +help, she had said, I must have left half my belongings behind, and I shall +have need of them.

+ +

“Shall you get far tonight?” wondered Rannilt, hesitant but anxious for +assurance.

+ +

“Out of this land, I hope. Iestyn, who is nobody here, has a kinship of his +own, and a place of his own, in his own country. There we shall be safe enough +together. After tonight, if we make good speed, we cannot be pursued. You are +not afraid, Rannilt, coming all this way with me in the dark?”

+ +

“No,” said Rannilt sturdily, “I’m not afraid. I wish you well, I wish you happy, +I’m glad to carry your goods for you, and to know that you don’t go +unprovided.”

+ +

“No,” agreed Susanna, with a curious twist to her voice that suggested +laughter, “not quite penniless. I have earned my future, have I not? Look back +now,” she said, “over your left shoulder, at that mole-hill of the town.” It +showed as a hunched shadow in the shadowy night, stray flickers of light cast +up the pale stone of the wall from the silver of the river in between. “A last +glimpse,” said Susanna, “for we have not far now to go. Has the load been +heavy? You shall soon lay it down.”

+ +

“Not heavy at all,” said Rannilt. “I would do more for you if I could.”

+ +

The track along the headlands was rough and rutted, but Susanna knew it +well, and stepped securely. On their right the ground rose, its darkness furred +and fragrant with trees. On their left the smooth green meadows swept down to +the lambent, murmuring Severn. Ahead, a roof heaved dimly out of the night, +bushes banked about it, rough ground sheltering it to northwards, the pasture +opening serenely to the south.

+ +

“We are there,” said Susanna, and hastened her step, so that Rannilt hurried +to keep up with her and balance their burden.

+ +

Not a large building, this one that loomed out of the night, but stout in +its timbers, and tall enough to show that above the stable it had a loft for +hay and fodder. There was a double door set wide upon deep darkness, out of +which the scent of horseflesh and hay and grainy, dusty warmth came to meet +them. A man emerged, a dark shape, tensed to listen for any approaching foot. +Susanna’s step he knew at once and he came with spread arms; she dropped her +end of the bundle and opened her arms to him. Not a word, not a sound had +passed between them. Rannilt stood clutching her end of the load, and shook as +though the earth had trembled under her, as they came together in that silent, +exultant embrace, laced arms straining. Once at least, if never again, she had +experienced a small spark of this devouring flame. She closed her eyes, and +stood quivering.

+ +

Their breaking apart was as abrupt and silent as their coming together. +Iestyn looked over Susanna’s shoulder, and fixed his black glance on Rannilt. “Why +did you bring the girl? What do we want with her?”

+ +

“Come within,” said Susanna, “and I’ll tell you. Have you saddled up? We +should get away quickly.”

+ +

“I was about it when I heard you.” He picked up the roll of clothing, and +drew her with him into the warm darkness of the stable and Rannilt followed +timidly, only too aware how little need they now had of her. Iestyn closed the +doors, but did not fasten them. “Who knows, there may still be some soul awake +along the river, no need to let them see any movement here until we’re away.”

+ +

She heard and felt them embrace again in the dark, even in this brief contact +becoming one by passionate consent. She knew then that they had lain together +as she and Liliwin had lain, but many times and with no better hope. She +remembered the rear door of Susanna’s chamber and the stair to the undercroft +not many yards distant. Every temptation lavishly offered, and all countenance +denied.

+ +

“This child here,” said Iestyn softly, “what’s your intent with her? Why did +you bring her all this way?”

+ +

“She sees too clear and notices too much,” said Susanna shortly. “She has +said to me, poor fool innocent, things she had better not have said, and had +better not say to any other, for if they understood more than she by it, they +might yet be the death of us. So I brought her. She can go with us—a part of +the way.”

+ +

Iestyn demanded, after a brief, deep silence: “What do you mean by that?”

+ +

“What do you suppose? There are woods enough and wild places your side the +border. Who’s to look for her? A kinless kitchen slave.” The voice was so +calmly and reasonably Susanna’s voice that Rannilt could not take in what it +was saying, and stood utterly lost and feeling herself forgotten, even while +they spoke of her.

+ +

A horse stamped and shifted in the dark, the warmth of its big body +tempering the night air. Shapes began to emerge faintly, shadow separating +itself from shadow, while Iestyn breathed long and deeply, and suddenly +shuddered. Rannilt felt him quake, and still did not understand.

+ +

“No!” he said in a muted cry just below his breath. “No, that we cannot, +that I will not. Good God, what harm has she ever done us, a poor soul even +less happy than we?”

+ +

“You need not,” said Susanna simply. “I can! There is nothing now I cannot +do to have you mine, to belong to you, to go by your side through this world. +After what I’ve done already, what is there I dare not do?”

+ +

“No, not this! Not this offence, not if you love me. The other was forced on +you, what loss was he, as mean as your kin! But not this child! I will not let +you! Nor’s there no need,” he said, turning from ordering to persuading. “Here +are we, well out of the town, leave her here and go, you and I together, what +else matters here? Let her make her way back by daylight. Where shall we be? +Far past pursuit, over the border into Welsh land, safe. What harm can she do +us, who has never done any yet, nor ever willed any?”

+ +

“They will pursue! If ever my father gets to know… You know him! He +would not stir a step for me, but for this—this…” She spurned with her foot the +bundle she had brought with her, and it rang faintly in the dark. “There could +be barriers on the way into Wales, accidents, delays… Far better be sure.”

+ +

“No, no, no! You shall not so despoil my love, I will not have you so changed. +I want you as you are now…”

+ +

The horses shifted and blew, uneasy at having disturbing company at this +hour, yet wakeful and ready. Then there was a silence, brief and fathoms deep, +and ending in a long-drawn sigh.

+ +

“My heart, my love,” Susanna said in a melting whisper, “as you will, as you +order… Have it your way, then… Yes, let her be! What if we are hunted? There’s +nothing I can refuse you—not my life…”

+ +

And whatever it had been between them, and concerning her, it was over. +Rannilt stood helpless in the corner of the stable, trying to understand, +willing them away, westward into Wales, where Iestyn was a man and a kinsman +instead of a menial, and Susanna might be an honourable wife, who had been +hitherto a household servant, baulked of her rights, grudged her dowry, a +discard woman.

+ +

Iestyn plucked up the clothing roll, and by the stirring and trampling of +one of the horses, he was busy strapping it into balance behind the saddle. The +other bundle, the heavy one, gave forth again its soft, metallic sound as +Susanna hoisted it, to be stowed behind the second mount. They were still +barely visible, those horses. An occasional splinter of light glanced from +their coats and was lost again; their warmth breathed on the air with every +movement.

+ +

A hand swung wide the half of the double door, and a sector of sky peered +in, lighter than the darkness, bluer than the blackness, growing luminous with +the rising of a half-moon. One of the horses stirred into motion, led towards +that paler interstice.

+ +

There was a short, sharp cry, so soft and desolate that the air ached with +it. The opened half-door slammed to again, and Rannilt heard hasty hands +fumbling with heavy bars, hoisting and dropping them into solid sockets. Two +such beams guarding the door had the force and assurance of a fortress.

+ +

“What is it?” Susanna’s voice pealed sharply out of the dusk within. She was +holding the bridle, the abrupt halt made the horse stamp and snort.

+ +

“Men, a good number, coming down from the headland! There are horses, led +behind! They’re coming here—they know!”

+ +

“They cannot know!” she cried.

+ +

“They do know. They’re spreading, to ring us round, I saw the ranks part. +Get up the ladder! Take her with you. She may be worth all to us yet. What +else,” he cried, suddenly raging, “have we between ourselves and the +judgement?”

+ +

Rannilt, bewildered and frightened, stood trembling in the darkness, stunned +by the confusing turmoil of hooves stamping round her, and bodies in violent, +blind motion, warm stable smells eddying on the air and pricking her nostrils +as the stirrings of terror prickled her skin. The doors were barred, and Iestyn +between her and that way out, even if she could have lifted the beams. And +still she could not believe, could not take in what was happening to her, or +relate these two desperate people with the Susanna and the Iestyn she had +known. When a hand gripped her wrist and tugged her towards the rear corner of +the stable, she went helplessly with the urgent compulsion. What else could she +do? Her ankle struck against the lowest rung of a ladder, the hand dragged her +upwards. Fumbling and panting, she went where she was hauled, and was tossed face-down +into a pile of hay that enveloped her in dust and dry sweetness. Dimly she was +aware of punctures of sky shining through the hay, distinguishably paler in the +timber darkness before her, where whoever built this stable and loft had placed +a ventilation lattice to air his store.

+ +

Somewhere behind her, at the door end of the loft, a larger square of sky +looked in, the hatch by which the hay harvest was forked in here for storage, +high above the barred doors below. She heard the rungs of the ladder creak at +Iestyn’s weight as he climbed in haste, and ran to fling himself on his knees +beside that outlet, to watch his enemies close about his refuge. She heard, and +suddenly was able to comprehend what she heard. The thud of fists hammering on +the barred doors, the challenge of the law without.

+ +

“Open and come forth, or we’ll hack you out with axes. We know you there +within and know what you have to answer for!”

+ +

Not a voice she knew, for an eager sergeant had outrun his lord and his +fellows when he heard the bars slam home, and had come well first to the doors. +But she knew the import of what he bellowed to the night, and understood fully +at last into what peril she had been brought.

+ +

“Stand back!” Iestyn’s voice rang loud and hard. “Or answer to God for a life, +you also! Well away from those doors, and don’t venture back, for I see you +clearly. And I’ll speak no more with you, underling, but only with your master. +Tell him I have a girl here between my hands, and a knife at my belt, and so +sure as axe strikes at these timbers, my knife slits her throat. Now bring me +here someone with whom I can parley.”

+ +

There was a sharp command without and then silence. Rannilt drew herself +back as far as she dared into the remaining store of hay, towards the faint +pattern of stars. Between here and the head of the ladder by which she had +climbed there was a silent, motionless presence which she knew for Susanna, on +guard over her lover’s only weapon.

+ +

“What did I ever do to you?” said Rannilt, without rancour or hope.

+ +

“You fell foul,” said Susanna, with unblaming bitterness. “Your misfortune +and ours.”

+ +

“And will you truly kill me?” She asked it in pure wonder, even her terror +momentarily forgotten.

+ +

“If we must.”

+ +

“But dead,” said Rannilt, in a moment of desperately clear vision putting +her finger on the one disastrous weakness in the holding of hostages, “I am of +no more use to you. It’s only living that I can get you what you want. +If you kill me you’ve lost everything. And you don’t want to kill me, +what pleasure would that be to you? Why, I’m no use to you at all!”

+ +

“If I must pull the roof down upon myself,” said Susanna with cold ferocity, +“I’ll pull it down also upon as many of the innocent as I can contrive to crush +with me and not go alone into the ark.”

+
+
+

Chapter Thirteen

+ +

« ^ »

+ +

Friday night to Saturday morning

+ +

Hugh had +halted his men instantly at Iestyn’s challenge, drawn back those who had +reached the stable doors, and enjoined silence, which is more unnerving than violent +assault or loud outcry. Moving men could be detected, stillness made them only +dubiously visible. The rising ground to the headland bore several small clumps +of trees and a hedge of bushes, cover enough for men to make their way halfway +round the stable, and the rest of the circle they closed at a greater distance, +completing a ring all round the building. The sergeant came back from his +survey, shadowy from tree to tree down the slope to the meadow, to report the +stable surrounded.

+ +

“There’s no other way out, unless he has the means to hew a way through a +wall, and small good that would do him. And if he boasts of a knife, I take it +he has no other weapon. What would a common workman carry but his knife for all +purposes?”

+ +

“And we have archers,” mused Hugh, “if they have no light to show them a +target as yet. Wait—nothing in haste! If we have them securely, it’s we who can +afford to wait, not they. No need to drive them to madness.”

+ +

“But they have Rannilt in there—they’re threatening her life,” whispered +Liliwin, quivering at Brother Cadfael’s shoulder.

+ +

“They’re offering to spend her for their own ends,” said Hugh, “therefore +all the more they’ll keep her safe to bargain with, short of the last despair, +and I’ll take good care not to drive them over the edge. Keep still a while, +and let’s see if we can tire them out or talk them out. But you, Alcher, find +yourself the best place in cover to command that hatch above the doors, and +keep it in your eye and a shaft always ready, in case of the worst. I’ll try to +hold the fellow there in the frame for you.” The loading door where Iestyn +kneeled to watch them was no more than a faint shape darker still in the dark +timber wall and the deep-blue light, but like the doors it faced due east, and +the first predawn light, however many hours away yet, would find it early. “No +shooting unless I bid. Let’s see what patience can do.”

+ +

He went forward alone, fixing the square of darkness with intent eyes, and +stood some twenty paces distant from the stable. Behind him in the bushes +Liliwin held his breath, and Brother Cadfael felt the boy’s slight body +quivering and taut, like a leashed hound, and laid a cautioning hand on his arm +in case he slipped his leash and went baying after his quarry. But he need not +have feared. Liliwin turned a white face and nodded him stiff reassurance. “I +know. I trust him, I must. He knows his business.”

+ +

At their backs, unable to be still, Walter Aurifaber sidled and writhed +about the tree that sheltered him, biting his nails and agonising over his +losses, and saying never a word to any but himself, and that in a soft, whining +undertone that was half malediction and half prayer. At least all was not yet +lost. The malefactors had not escaped, and could not and must not break loose +now and run for it westward.

+ +

“Iestyn!” called Hugh, gazing steadily upward. “Here am I, Hugh Beringar, +the sheriff’s deputy. You know me, you know why I am here, you best know I am +about what it is my duty to do. My men are all round you, you have no way of +escape. Be wise, come down from there and give yourself—yourselves—into my +hands, without more damage and worse offence, and look for what mercy such good +sense can buy you. It’s your best course. You must know it and take heed.”

+ +

“No!” said Iestyn’s voice harshly. “We have not come so far to go tamely to +judgement now. I tell you, we have the girl, Rannilt, here within. If any man +of yours comes too near these doors, I swear I will kill her. Bid them keep +back. That’s my first word.”

+ +

“Do you see any man but myself moving within fifty paces of your doors?” +Hugh’s voice was calm, equable and clear. “You have, then, a girl at your +mercy. What then? With her you have no quarrel. What can you gain by harming +her but a hotter place in hell? If you could reach my throat, I grant you it +might possibly avail you, but it can neither help you nor give you satisfaction +to slit hers. Nor does it suit with what has been known of you heretofore. You +have no blood-guilt on your hands thus far, why soil them now?”

+ +

“You may talk sweet reason from where you stand,” cried Iestyn bitterly, “but +we have all to lose, and see no let to making use of what weapons we have. And +I tell you, if you press me, I will kill her, and if then you break in here after +me by force, I will kill and kill as many as I can before the end. But if you +mean such soft, wise talk, yes, you may have the girl, safe and sound—at a +price!”

+ +

“Name your price,” said Hugh.

+ +

“A life for a life is fair. Rannilt’s life for my woman’s. Let my woman go +free from here, with her horse and goods and gear and all that is hers, +unpursued, and I will send out the girl to you unharmed.”

+ +

“And you would take my word there should be no pursuit?” Hugh pressed, +angling after at least a small advantage.

+ +

“You’re known for a man of your word.”

+ +

Two voices had let out sharp gasps at the mention of such terms, and two +voices cried out: “No!” in the same breath. Walter, frantic for his gold and +silver, darted out a few steps towards where Hugh stood, until Cadfael caught +him by the arm and plucked him back. He wriggled and babbled indignantly: “No, +no such infamous bargain! Her goods and gear? Mine, not hers, stolen +from me. You cannot strike such a bargain. Is the slut to make off into Wales +with her ill-gotten gains? Never! I won’t have it!”

+ +

There was a shadowy flurry of movement in the hatch above, and Susanna’s +voice pealed sharply: “What, have you my loving father there? He wants his +money, and my neck wrung, like that of any other who dared lay hands on his +money. Poor judgement in you, if you expected him to be willing to pay +out a penny to save a servant-girl’s life, or a daughter’s either. Never fear, +my fond father, I say no just as loudly as you. I will not accept such a +bargain. Even in peril of death I would not go one step away from my man here. +You hear that? My man, my lover, the father of my child! But on terms I’ll part +from him, yes! Let Iestyn take the horse, and go back unmolested into his own +country, and I’ll go freely, to my death or my wretched life, whichever falls +on me. I am the one you want. Not he. I have killed, I tell +you so open…”

+ +

“She’s lying,” cried Iestyn hoarsely. “I am the guilty man. Whatever she did +she did only for me…”

+ +

“Hush, love, they know better! They know which of us two planned and acted. +Me they may do as they like with—you they shall not have!”

+ +

“Oh, fool girl, my dearest, do you think I would leave you? Not for all the +world’s treasures…”

+ +

Those below were forgotten in this wild contention above. Nothing was to be +seen but the agitated tremor of certain pallors within the dark frame, that +might have been faces and hands, faces pressed despairingly cheek to cheek, +hands embracing and caressing. Next moment Iestyn’s voice lifted sharply: “Stop +her! Quickly, stir! Mind your fawn!” And the shadowy embrace broke apart, and a +faint, frustrated cry from deep within made Liliwin shiver and start against +Cadfael’s arm.

+ +

“That was Rannilt. Oh, God, if I could but reach her…” But he spoke only in +a whisper, aware of a tension that ought not to be broken, that was spun out +here like the threatened thread of Rannilt’s young life, and his own hope of +happiness. His desperation and pain was something he must bear, and keep +silent.

+ +

“Since she cries out,” whispered Cadfael firmly into his ear, “she is alive. +Since she made a bid to slip away out of reach while they were beset, she is +unharmed and unbound. Keep that in mind.”

+ +

“Yes, true! And they don’t, they can’t hate her or want to harm her…” But +still he heard the extreme anger and pain of those two voices crying defiance, +and knew, as Cadfael knew, that two so driven might do terrible things even +against their own natures. More, he understood their suffering, and was wrung +with it as though it matched his own.

+ +

“No comfort for you,” shouted Iestyn from his lair. “We have her still. Now +I offer you another choice. Take back the girl and the gold and silver, give us +the two horses and this night free of pursuit, together.”

+ +

Walter Aurifaber broke free with a whimper of half-eager, half-doubtful hope +and approval, and darted some yards into the open. “My lord! My lord, that +might be acceptable. If they restore my treasury…” Even his lawful revenge did +not count for much by comparison.

+ +

“There is a life they cannot restore,” said Hugh curtly, and motioned him +back so sternly that the goldsmith recoiled, chastened.

+ +

“Are you listening, Iestyn?” called Hugh, raising his eyes once again to the +dark hatch. “You mistake my office. I stand here for the king’s law. I am +willing to stand here all night long. Take thought again, and better, and come +down with unbloodied hands. There is no better thing you can do.”

+ +

“I am here. I am listening. I have not changed,” Iestyn responded grimly +from above. “If you want my woman and me, come and fetch us forth, and fetch +away first this little carcase—your prey, not ours.”

+ +

“Have I raised a hand?” said Hugh reasonably. “Or loosened my sword in the +scabbard? You see me, clearer than I can see you. We have the night before us. +Whenever you have ought to say, speak up, I shall be here.”

+ +

The night dragged with fearful slowness over besiegers and besieged, for the +most part in mourn silence, though if silence continued too long Hugh would +deliberately break it, to test whether Iestyn remained awake and watchful, +though with care not to alarm him, for fear he should be driven to panic action +in expectation of an attack. There was no remedy but to outwait and out endure +the enemy. In all likelihood they had very little food or water with them. They +could as easily be deprived of rest. Even in such tactics there was the danger +of sudden and utter despair, which might bring on a massacre, but if all was +done very gradually and softly that might yet be avoided. Weariness has +sometimes broken down spirits braced implacably to defy torture, and inaction +sucked away all the resolution armed for action.

+ +

“Try if you can do better,” said Hugh softly to Cadfael, some time well past + midnight. “They cannot know you’re here, not yet, you may find a chink in their +mail that’s proof against me.”

+ +

In those small hours when the heart is low, the least surprise may prick +home as it could not do by day, in the noon of the body’s vigour. Cadfael’s +very voice, deeper and rougher than Hugh’s, startled Iestyn into leaning out +from his watch-tower for one incautious stare at this new visitant.

+ +

“Who’s that? What trick are you playing now?”

+ +

“No trick, Iestyn. I am Brother Cadfael of the abbey, who came sometimes to +the house with medicines. You know me, I dare not say well enough to trust me. +Let me speak with Susanna, who knows me better.”

+ +

He had thought that she might refuse either to speak or to hear him. When +she had set her mind upon one course, she might well be stone to any who sought +to divert her or stand in her way. But she did come to the hatch, and she did +listen. At least that was a further respite. Those two lovers changed places in +the loft. Cadfael felt them pass, and now they passed without touching or +caressing, for there was no need. They were two halves of one whole, living or +dead. One of them, it was clear from the earlier outcry, must keep an eye on +their prisoner. They could not bind her, then, or else they had not thought it +needful. Perhaps they had not the means. They were trapped in the instant of +flight. Was it unpardonable to wish they had ridden away half an hour earlier?

+ +

“Susanna, it is not too late to make restitution. I know your wrongs, my +voice shall speak for you. But murder is murder. Never think there is any +escape. Though you elude the judgement here, there is another you cannot avoid. +Better far to make what amends can be made and be at peace.”

+ +

“What peace?” she said, bitter and chill. “There is none for me. I am a +stunted tree, denied the ground to grow, and now, when I am in fruit, in +despite of this world, do you think I will abate one particle of my hate or +love? Leave me be, Brother Cadfael,” she said more gently. “Your concern is +with my soul, mine is all with my body, the only heaven I’ve ever known or ever +hope to know.”

+ +

“Come down and bring Iestyn with you,” said Cadfael simply, “and I take it +upon myself to promise you, as I must answer to God, that your child and his +shall be born and cared for as befits every human soul brought innocent into +the world. I will invoke the lord abbot to ensure it.”

+ +

She laughed. It was a fresh, wild and yet desolate sound. “This is not Holy Church’s +child, Brother Cadfael. It belongs to me, and to Iestyn my man, and there is +none other shall ever cradle or care for it. Yet I do thank you for your goodwill +to my son. And after all,” she said, with bitter derision in her voice, “how do +we know the creature would ever be brought forth living and whole? I am old, +Brother Cadfael, old for childbirth. The thing may be dead before me.”

+ +

“Make the assay,” said Cadfael stoutly. “He is not wholly yours, he is his +own, your maybe child. Do him justice! Why should he pay for your sins? It was +not he trampled Baldwin Peche into the gravel of Severn.”

+ +

She made a dreadful, muted sound, as if she had choked upon her own rage and +grief, and then she was calm and resolved again, and immovable. “Three are here +together and made one,” she said, “the only trinity I acknowledge now. No +fourth has any part in us. What do we owe to any man living?”

+ +

“You forget there is a fourth,” said Cadfael strongly, “and you are making +shameful use of her. One who is none of yours and has never done you wrong. She +also loves—I think you know it. Why destroy another pair as little blessed as +you?”

+ +

“Why not?” said Susanna. “I am all destruction. What else is left to me +now?”

+ +

Cadfael persisted, but after a while, talking away doggedly there past the +mid of the night, he knew that she had risen and left him, unconvinced, +unreconciled, and that it was Iestyn who now leaned in the hatch. He waited a +considering while, and then took up his pleading for this perhaps more +vulnerable ear. A Welshman, less aggrieved than the woman, for all his +hardships; and all Welsh are kin, even if they slit one another’s throats now +and then, and manure their sparse and stony fields with fratricidal dead in +tribal wars. But he knew he had little hope. He had already spoken with the +domina of that pair. There was no appeal to this one now that she could not +wipe out with a gesture of her hand.

+ +

He was eased, if not verily glad, when Hugh came back to relieve him of his +watch.

+ +

He sat slack and discouraged in the spring grass under the hedge of bushes, +and Liliwin came plucking softly but urgently at his sleeve. “Brother Cadfael, +come with me! Come!” The whisper was excited and hopeful, where hope was in no +very lavish supply.

+ +

“What is it? Come with you where?”

+ +

“He said there’s no other way out,” whispered Liliwin, tugging at the sleeve +he held, “and by that token none in, but there is… there could be. Come and +see!”

+ +

Cadfael went where he was led, up through the bushes on the headland, and +along the slope in cover, just below the level of the stable roof and at no +great distance from it, to the western end of the building. The timbers of the +roof projected above the low gable, the fellow to the eastern one in which +Iestyn crouched on watch. “See there—the starlight shows dappling. They let in +a lattice there for air.”

+ +

Peering narrowly, Cadfael could just discern a square shape that might well +be what Liliwin described, but measured barely the span of hand and forearm +either way, as close as he could estimate. The interstices between the slats, +which the straining eye could either discern or imagine for a moment, only to +lose them again, were surely too small even to admit a fist. Nor was there any +way of reaching them, short of a ladder or the light weight and claws of a cat, +even though the timbers of the wall below were rough and uneven.

+ +

“That?” breathed Cadfael, aghast. “Child, a spider might get up there and +get in, but scarcely a man.”

+ +

“Ah, but I’ve been down there, I know. There are toe-holds enough. And I +think one of the slats is hanging loose already, and there’ll be others ready +to give way. If a man could get in there, while you hold them busy at the other +end… She is up there, I know it! You heard, when they ran to hold her, how far +it was to run.”

+ +

It was true. Moreover, if she had any choice she would be huddled as far +away from her captors as she could get.

+ +

“But, boy, even if you stripped away two or three of the boards—could you do +more, unheard? I doubt it! There’s not a man among us could get through that +keyhole to her. No, not if you had time to strip the whole square.”

+ +

“Yes, I can! You forget,” whispered Liliwin eagerly, “I’m small and +light and I’m an acrobat, bred to it from three or four years old. It’s my +craft. I can reach her. Where a cat can go I can go. And she’s even +smaller than I, though she may not be trained as a tumbler. If I had a rope, I +could make it fast there, and take my time opening up the way for her. Oh, +surely, surely it’s worth the attempt! We’ve no other way. And I can +do it, and I will!”

+ +

“Wait!” said Cadfael. “Sit you here in cover, and I’ll go broach it to Hugh +Beringar and get you your rope, and make ready to hold them fast in talk, as +far as may be away from you. Not a word, not a movement until I come back.”

+ +

“No madder than whatever else we may do to break this dam,” said Hugh when he +had listened and considered. “If you put some trust in it, I’ll go with you. +Can he really creep in there, do you think? Is it possible?”

+ +

“I’ve seen him tie himself in a knot a serpent might be proud of,” said +Cadfael, “and if he says there’s room enough there for him to pass, I say he’s +the better judge of that than I. It’s his profession, he takes pride in it. +Yes, I put my trust in him.”

+ +

“We’ll send to fetch him his rope, and a chisel, too, to pry loose the +slats, but he must wait for them. We’ll make good certain they stay wakeful and +watchful at this end, and try a feint or two, if need be, short of driving them +to panic. And let him take his time, for I think we might be advised to wait +for the first light, to give Alcher a clear view of that hatch and whatever +body fills it, and a shaft fitted and aimed in case of need. If we must let a +decent poor lad risk his life, at least we’ll stand ready with all the cover we +can give him.”

+ +

“I had rather,” said Cadfael sadly, “there should be no killing at all.”

+ +

“So would I,” agreed Hugh grimly, “but if there must be, rather the guilty +than the innocent.”

+ +

The dawn was still more than an hour and a half away when they brought the +rope Liliwin needed, but already the eastern sky had changed, turned from +deepest blue to paler blue-green, and a faint line of green paler still +outlined the curves of the fields behind them, and the towered hill of the +town.

+ +

“Rather round my waist than my neck,” whispered Liliwin hardily, as Cadfael +fastened the rope about him among the bushes.

+ +

“There, I see you have the true spirit in you. God keep you, the pair of +you! But can she come down the rope, even if you reach her? Girls are not such +acrobats as you.”

+ +

“I can guide her. She’s so light and small, she can hold by the rope and +walk backwards down the wall… Only keep them busy there at the far end.”

+ +

“But go slowly and quietly, no haste,” cautioned Cadfael, anxious as for a +son going into battle. “I shall be running messenger between. And daylight will +be on our side, not on theirs.”

+ +

Liliwin kicked off his shoes. He had holes in the toes of both feet of his +hose, Cadfael saw. Perhaps none the worse for this enterprise, but when he came +to be sent out into the world—God so willing, as surely God must—he must go +better provided.

+ +

The boy slid silently down from the headland to the foot of the stable wall, +felt with stretched arms above his head, found grips a heavier man would never +have considered, set a toe to a first hold, and drew himself up like a squirrel +on to the timbers.

+ +

Cadfael waited and watched until he had seen the rope slipped through the +firmest boards of the lattice and made fast, and the first rotten slat prised +free, slowly and carefully, and let fall silently at arm’s-length into the +thick grass below. More than half an hour had passed by then. From time to time +he caught the sound of voices in weary but alert exchanges to eastward. The +criss-cross of boards at the air-vent showed perceptibly now. The removal of +one board had uncovered a space big enough to let a cat in and out, but surely +nothing larger or less agile. The vault of the sky lightened very gradually +before there was any visible source of light.

+ +

Liliwin worked with a bight of the tethered rope fast round him, and +half-naked toes braced into the timbers of the wall. He had begun patiently +prising loose the second slat, when Cadfael made his way back in cover to +report what he knew.

+ +

“God knows it looks impossible, but the lad knows his business, and if he is +sure he can pass, as a cat knows by its whiskers, then I take his word for it. +But for God’s sake keep this parley alive.”

+ +

“Take it over for me,” said Hugh, drawing back with eyes still fixed on the +hatch. “Only some few moments… A fresh voice causes them to prick their ears +afresh.”

+ +

Cadfael took up the vain pleas he had used before. The voice that answered +him was hoarse with weariness, but still defiant.

+ +

“We shall not go from here,” said Cadfael, roused out of his own weariness +by a double anxiety, “until all these troubled here, body and soul, have +freedom and quiet, whether in this world or another. And who so prevents to the +last, on him the judgement fall! Nevertheless, God’s mercy is infinite to those +who seek it, However late, however feebly.”

+ +

“The light will not be long,” Hugh was saying at that same moment to Alcher, +who was the finest marksman in the castle garrison, and had long since chosen +his ground with the dawn in view, and found no reason to change it. “Be ready, +the instant I shall call, to put an arrow clean into that hatch, and through +whoever lurks there. But no shooting unless I do call. And pray God I am not +forced to it.”

+ +

“That’s understood,” said Alcher, nursing his strung bow and fitted shaft, +and never shifting his eyes from their aim, dead-centre of the dark opening, +now growing clearly visible above the stable doors.

+ +

When Cadfael again made his way along the headland, the lattice was a +lattice no longer, but a small square opening under the eaves, and the +dislodged slats lay cushioned in the thick grass below. Liliwin had one arm +stretched within, to ease aside the hay cautiously, with as little sound as +possible, and make room to creep within. Now if only Rannilt could keep from +starting or crying out when she found herself approached thus from behind! It +was high time to make as much and as menacing ado before the stable doors as +possible. Yet Cadfael could not help standing with held breath to watch, until +Liliwin slid head and shoulders through the space that seemed barely passable +even for his slenderness, and drew the rest of himself after in one coiling, +rapid movement, vanishing in a smooth somersault, and without a sound.

+ +

Cadfael made his way back in haste to a point still out of sight from the +hatch, and signalled urgently to Hugh that the time of greatest danger was +come. Alcher saw the waving arm before Hugh did, and drew his bow halfway to +the ear, narrowing his eyes upon the moving blurs of drab brown coat and paler +face that showed as his target. Behind him the sun was just showing a rim over +the horizon, and its first ray gleamed along the ridge of the roof. In a +quarter of an hour it would be high enough for the light to reach the hatch, +and the shot would be an easy matter.

+ +

“Iestyn,” called Hugh sharply, mustering those of his men nearest him into +plain sight, though not too near to the doors, “you have had a night’s grace to +consider, now show decent sense, and come forth of your own will, for you see you +cannot escape us, and you are mortal like others, and must eat to live. You are +not in sanctuary there, there are no forty days of respite for you.”

+ +

“There’s nothing but a halter for us,” shouted Iestyn savagely, “and well we +know it. But if that’s our end, I swear to you the girl shall go before us, and +her blood be on your head.”

+ +

“So you say, big talk from a small man! Your woman may not be so ready +either to kill or to die. Have you asked her? Or have you the only voice in the +matter? Here, master goldsmith,” called Hugh, beckoning, “come and speak to +your daughter. However late in the day, she may still listen to you.”

+ +

He was bidding to sting her, to bring them both flying to the hatch to spit +their joint defiance and leave their prisoner unwatched. But oh, not too fast, +not too fast, prayed Cadfael, gnawing his knuckles on the headland. The boy +needs a few more minutes yet…

+ +

Liliwin tunnelled stealthily through the stored hay, as much in terror of +sneezing, as the odorous dust tickled his nostrils, as he was of making too +audible a rustling and betraying himself all too soon. Somewhere before him, +very close now, he could hear the faint stirrings Rannilt made in her nest, and +prayed that they would cover whatever sound he was making. After a while, pausing +to peer through the thinning screen, he caught the shape of her shrinking +shoulders and head against the dim morning light. Carefully he enlarged the +passage he had hollowed out, so that he might have room to draw to one side of +her, and have her creep past him, to come first to the frame of the lattice. +Iestyn was leaning out at the far end of the loft, shouting angry curses now at +those without, threatening still but not looking this way.

+ +

There was a woman to fear, for wherever she was now, she was silent. But +surely if those without were pressing, half at least of her care must be with +her lover. And here in the loft it was still blessedly dark.

+ +

His hand, probing delicately ahead, found and touched Rannilt’s bare +forearm. She flinched sharply, but made no sound at all, and in a moment he +slid his hand down to find hers, and clung. Then she knew. All he heard was a +faint, long sigh, and her fingers closed on his. He drew her gently, and by +slow inches she shifted and drew nearer, into the cavity he opened for her. She +was beside him, the fragile screen of hay hiding him and already half shielding +her, and still no outcry. He urged her on past him with the pressure of his +hand, to come first to the lattice and the rope as he covered her going. +Outside the stable doors the circling voices were raised and peremptory, and +Iestyn, wild with weariness and anger, roared back at them incoherent defiance. +Then, blessedly, Sussana’s voice, surely close there at her lover’s shoulder, +soared above the clamour:

+ +

“Fools, do you think there’s any power can separate us now? I hold as Iestyn +holds, I despise your promises and your threats as he does. Bring my father to +plead with me, would you? Let him hear, then, what I owe him, and what I wish +him. Of all men on earth, I hate him! As he has made me of no worth, so I set +no value on him. Dare he say I am no longer his daughter? He is no longer my father, +he never was a father to me. May he be fed molten gold in hell until belly and +throat burn to furnace ashes…”

+ +

Under the fury of that raging voice, clear and steely as a sword, Liliwin +hustled Rannilt past him and thrust her bodily through his dusty tunnel towards +the lattice and the rope, all caution cast to the winds, for if this momemt +escaped them, there might be no other.

+ +

It was Iestyn’s quick ear that caught, even through Susanna’s malediction, +the sudden frenzied rustling of hay. He swung round with a great cry of rage at +what he saw, and lunged away to prevent it. The first ray of light entering +caught the flash of the naked knife.

+ +

Hugh was quick to understand and act. “Shoot!” he cried, and Alcher, who had +that first finger of sunlight now bright on Iestyn’s body, loosed his shaft. +Meant for the breast, it would have been no less mortal in the back, if +Susanna, for all her bitter passion, had not taken in all these signs in one +breath. She uttered a shriek rather of rage than fear, and flung herself into +the opening of the hatch, arms spread and braced to ward off her lover’s death.

+ +

At the first cry Liliwin had thrust Rannilt towards the way of escape, and +sprung erect out of the hay to put his own slight body between her and harm. +Iestyn bore down on him, the brandished dagger caught the levelled ray of sun +and sent splinters of light dancing about the roof. The blade hung over +Liliwin’s heart when Susanna’s shriek caused Iestyn to baulk and shudder where +he stood, straining backwards like a horse suddenly reined in, and the point of +the knife slid wildly down, slicing along the boy’s parrying forearm, and +drawing a fine spray of blood into the hay.

+ +

She was melting, she was dissolving into herself, as a man of snow folds +into himself gradually when the thaw comes. The impact of the arrow, striking +full into her left breast, had spun her round, she sank slowly with her hands +clutching the shaft where it had pierced her, and her eyes fixed, huge and +clouded, upon Iestyn, for whom the death had been intended. Liliwin, dazedly +watching as the man sprang back to clasp her, said afterwards that she was +smiling. But his recollections were confused and wild, what he chiefly recalled +was a terrible howl of grief and despair that filled and echoed through the +loft. The knife was flung aside, and stuck quivering in the boards of the +floor. Iestyn embraced his love, moaning, and sank with her in his arms. Round +the fearful barrier of the arrow she essayed to lift her failing arms to clasp +him. Their kiss was a contortion the trained contortionist in Liliwin +remembered lifelong with pity and pain.

+ +

Liliwin came to himself soon, because he must. He drew Rannilt up by the +hand, away from the lattice of which they had no more need, and coaxed her +after him down the ladder to the stable floor where the loaded horses stamped +and shifted uneasily after all these nightlong alarms. He hoisted the heavy +bars that held the doors, and it took all the strength he had left to lift +them. The eastern light reached his face but no lower, as he pushed open both +heavy doors, and led Rannilt out into the green meadow.

+ +

They were aware of men flowing in as they came gladly out. Their part was +done. Brother Cadfael, breathing prayers of gratitude, took them both in his +arms, and swept them aside to a grassy knoll at the foot of the headland, where +they dropped together thankfully into the spring turf, and drew in the May air +and the morning light, and gradually turned and stared and smiled, like +creatures in a dream, waking to be glad of each other.

+ +

Hugh was first up the ladder and into the loft, the sergeant hard on his +heels. In the shaft of sunlight, bolder and broader now, and blindingly bright +above the lingering dimness of the hay-strewn floor, Iestyn kneeled with +Susanna in his arms, tenderly holding her up from the boards, for the shaft had +pierced clean through her, and jutted at her shoulder. Her eyes were already +filmed over as though with sleep, but still kept their fixed regard upon her +lover’s face, a mask of grief and despair. When the sergeant made to lay a hand +on Iestyn’s shoulder, Hugh waved him away.

+ +

“Let him alone,” he said quietly, “he will not run.” There was no future +left to run for, nowhere to run to, no one to run with. Everything he cared for +was in his arms, and would not be with him long.

+ +

Her blood was on his hands, on the lips and cheek that had caressed her +frantically for a moment, as though caresses could make all whole again. He had +given over that now, he only crouched and clasped her, and watched her lips +trying to form words to take all upon herself, and deliver him, but making no +sound, and presently ceasing to attempt it. He saw the light go out behind the +glassy grey of her eyes.

+ +

Not until then did Hugh touch him. “She is gone, Iestyn. Lay her down now +and come with us. I promise you she shall be brought home decently.”

+ +

Iestyn laid her in the piled hay, and got to his feet slowly. The climbing +sun fingered the knotted binding of the one bundle they had brought up here +with them. His dulled eyes fell upon it, and flamed. He plucked it from the +floor, and hurled it out through the hatch, to burst asunder in the grass of +the meadow, scattering its contents in a shower of sparks as the level beams +crept across the pasture.

+ +

A great howl of desolation and loss welled up out of Iestyn’s throat to bay +at the cloudless and untroubled sky:

+ +

“And I would have taken her barefoot in her shift!”

+ +

Outside in the pasture another aggrieved wail arose like an echo, as Walter +Aurifaber grovelled in the grass on his hands and knees, frantically clawing up +from among the tussocks his despised gold and silver.

+
+
+

Chapter Fourteen

+ +

prev ^

+ +

Afterwards

+ +

They took back +the living and the dead alike into Shrewsbury in the radiant, slanting light of +morning, Iestyn, mute now and indifferent to his fate, to a lodging in the +castle; Susanna, safe from any penalty in this world, to the depeopled +household from which three generations together would shortly be carried to the +grave. Walter Aurifaber followed dazedly, hugging his recovered wealth, and +regarding his daughter’s body with a faint frown of bewilderment, as though, +tugged between his loss and his gain, he could not yet determine what he should +be feeling. For after all, she had robbed him and vilified him at the end, and +if he had been deprived of a competent housekeeper, that was his sole serious +loss, and there was another woman at home now to take her place. And with +Daniel surely maturing and taking a pride in his own craftsmanship, he might +very well manage without having to pay a journeyman. Whatever conflict +disrupted Walter would soon be resolved in favour of satisfaction.

+ +

As for the two delivered lovers, bereft of words, unable to unlock eyes or +hands, Cadfael took them in charge and, mindful of the proprieties, of Prior +Robert’s chaste disapproval and Abbot Radulfus’ shrewd regard for the ordered +peace of the rule, thought well to speak a word in Hugh’s ear and enlist the +ready sympathy of Hugh’s lady. Aline welcomed Rannilt into her care with +delight, and undertook to provide and instruct her in everything a bride should +possess and know, to feed her plump and rosy, and coax into full light those +beauties in her which hitherto had gone veiled and unregarded.

+ +

“For if you intend to take her away with you,” said Cadfael, propelling the +half-reluctant Liliwin back over the bridge towards the abbey gatehouse, “you’d +best marry her here, where there’ll be shame-faced folk enough anxious to set +you up with small favours, to pay for their misuse of you earlier. No need to +despise the gifts of this world when they come honestly. And you’ll be doing +the givers a kindness, they’ll have made their peace with their consciences. +You come back to us, and don’t grudge a week’s waiting to make ready for your +marriage. You could hardly bring your girl back to share your bed in the +porch.” Or behind an altar, he thought but did not say. “She’ll be safe there +with Hugh’s lady, and come to you with every man’s goodwill.”

+ +

Cadfael was right. Shrewsbury had a bad conscience about Liliwin, as soon as +word of the scandalous truth was being passed round over market-stalls and shop +counters and traded along the streets. All those who had been too hasty in +hunting him took care to proffer small favours by way of redress. The provost, +who had taken no part, noted the sad state of the young man’s only pair of +shoes, and set an example by making him a fine new pair in which to resume his +travels. Other members of the guild merchant took the hint. The tailors +combined to clothe him decently. He bade fair to emerge better provided than +ever before in his life.

+ +

But the best gift of all came from Brother Anselm.

+ +

“Well, since you won’t stay and be celibate here among us,” said the +precentor cheerfully, “here is your own rebec ready for playing, and a good +leather bag to carry it in. I’m pleased with my work, it came out better than I +dared hope, and you’ll find it still has a very sweet voice, after all its +misadventures.” And he added sternly, while Liliwin embraced his recovered +treasure with a joy far more profound than if it had been gold and silver: “Now +bear in mind what you’ve learned here concerning the reading and writing of +music. Never lose your skills. Let me not be ashamed of my pupil when you come +this way and visit us again.”

+ +

And Liliwin poured out fervent thanks, and promises he might never be able +to keep, though he meant them with all his heart.

+ +

They were married at the parish altar, where Liliwin had first taken refuge, +by Father Adam, priest of the Foregate parish, in the presence of Hugh and +Aline Beringar, Brother Cadfael, Brother Oswin, Brother Anselm, and several +more of the brothers who felt a sympathetic interest in their departing guest. +Abbot Radulfus himself gave them his blessing.

+ +

Afterwards, when they had packed up their wedding clothes and put on the +everyday homespun in which they meant to set out together, they sought out Hugh +Beringar, who was sitting with Brother Cadfael in the ante-chamber of the +guest-hall.

+ +

“We should be off soon,” said Liliwin, speaking for both, “to get the best +of the day on the road to Lichfield. But we wanted to ask, before we go… His +trial must be weeks away, we might never hear. He won’t hang, will he?”

+ +

So little they had, those two, even if it was more than ever they had +possessed before, and yet they had so much that they could afford pity. “You +don’t want him to hang?” said Hugh. “He would have killed you, Rannilt. Or do +you not believe that, now it’s all past?”

+ +

“Yes,” she said simply, “I do believe it. I think he would have done it. I +know she would. But I don’t want his death. I never wanted hers. He won’t hang, +will he?”

+ +

“Not if my voice is heard. Whatever he may have done, he did not kill, and +all that he stole has been restored. Whatever he did was done at her wish. I +think you may set out with quiet minds,” said Hugh gently. “He’ll live. He’s +younger than she. He may yet take another, even if it must be a second-best.”

+ +

For whatever else might be called in question about those two unhappy +sinners, Rannilt had been a witness to the devoted and desperate love between +them.

+ +

“He may end as a decent craftsman, settled with wife and children,” said +Hugh. Children who would be born in peace, not buried still in the womb, like +Susanna’s child. Three months gone, was the physician’s estimate. Even if she +had not seized the opportunity of her brother’s wedding feast, she would have +had to make her bid for freedom very soon.

+ +

“He would have given himself up for her sake,” said Liliwin seriously, “and +so would she for him. And she did die for him. I saw. We both saw. She knew +what she did. Surely that must count?”

+ +

So it might, and so, surely, must the pity and prayers of two young +creatures so misused and so magnanimous. Who should more certainly prevail?

+ +

“Come,” said Brother Cadfael, “we’ll bring you through the gate and see you +on your way. And God go with you!”

+ +

And forth they went, hopefully and happily, the new leather bag slung +proudly on Liliwin’s shoulder. To a life that could never be less than hard and +insecure, he the wandering entertainer at fairs and markets and small manors, +she, no doubt, soon just as adept with that pure, small voice of hers, and a +dance or two to her husband’s playing. In all weathers, at all seasons, but +with luck finding a decent patron for the winter, and a good fire. And at the +very worst, together.

+ +

“Do you truly believe,” asked Cadfael, when the two little figures had +vanished along the Foregate, “that Iestyn also may have a life before him?”

+ +

“If he can make the effort. No one is going to press for his death. He is +coming back to life, not willingly, but because he must. There is a vigour in +him he can’t shift all on to the past. It will be a minor love, but he’ll marry +and breed yet.”

+ +

“And forget her?”

+ +

“Have I said so?” said Hugh, and smiled.

+ +

“Whatever she did of worst,” said Cadfael soberly, “came of that in her that +might have been best, if it had not been maimed. She was much wronged.”

+ +

“Old friend,” said Hugh, shaking his head with rueful affection, “I doubt if +even you can get Susanna into the fold among the lambs. She chose her way, and +it’s taken her far out of reach of man’s mercy, if ever she’d lived to face +trial. And now, I suppose,” he said, seeing his friend’s face still thoughtful +and undismayed, “you will tell me roundly that God’s reach is longer than +man’s.”

+ +

“It had better be,” said Brother Cadfael very solemnly, “otherwise we are all +lost.”

+
+ +/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8 +SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFB +EUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/w +AARCAH0ATgDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QA +tRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2J +yggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eX +qDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2 +uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL +/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvA +VYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dX +Z3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1 +dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDwIM2wc0nmHgA0wHjHv60Y +z0OKLE3HGQkkg49qY0jDGD+NdT4Q8Lw61ayzT3UsISQIAiBieM55PvXd6X8ItHvYedWvlkx +2RMZ/z711RwdSUeZLQnnPGWnkI6mm/aH6V7uPgfpLoca7eK3r5SEflkVTf4ERksV8REL2/w +BE5PH+/wDWpeEqIalc8TM7Y6UguGA6/rXtdx8D7OC3Z5fEEu8ZPyWqhcf99VzniL4a2GmaT +cXq6pPJ5SjapiHzHIH9aPqlS17Bc84W6kzyePrRLeSNGE3MccqM9OtetxfBm3a0ieXXJfMZ +VJCW42jPUZLc/pWjZ/AWzuAG/wCEpkRc97IH/wBnoeEqpXsLnR4WZ5Pc0Cd/WvoCL9nS3Iy +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 +iZRx9M/rRRQMaQM4x2/pRRRQM//9k= +
\ No newline at end of file diff --git a/opds_catalog/tests/data/badfile.fb2 b/opds_catalog/tests/data/badfile.fb2 new file mode 100644 index 0000000000000000000000000000000000000000..66d0f3d80c1408865506986932ef20839d33bfcb --- /dev/null +++ b/opds_catalog/tests/data/badfile.fb2 @@ -0,0 +1 @@ +This not fb2 file for tests diff --git a/opds_catalog/tests/data/badfile.zip b/opds_catalog/tests/data/badfile.zip new file mode 100644 index 0000000000000000000000000000000000000000..972d80eb57f481aef53ad5ca90655e3d5d9420e4 --- /dev/null +++ b/opds_catalog/tests/data/badfile.zip @@ -0,0 +1 @@ +This novalid zip file for tests diff --git a/opds_catalog/tests/data/books.zip b/opds_catalog/tests/data/books.zip new file mode 100644 index 0000000000000000000000000000000000000000..4594dc2c912ac94a4de187e1157846d46feba870 Binary files /dev/null and b/opds_catalog/tests/data/books.zip differ diff --git a/opds_catalog/tests/test_dl.py b/opds_catalog/tests/test_dl.py new file mode 100644 index 0000000000000000000000000000000000000000..7364127b1d550e2832e96f0a8efb45b32cb25ae4 --- /dev/null +++ b/opds_catalog/tests/test_dl.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + +from django.core.urlresolvers import reverse +from django.test import TestCase, Client +from django.utils.translation import ugettext as _ + + +class DownloadsTestCase(TestCase): + fixtures = ['testdb.json'] + + def setUp(self): + pass + + def test_download_book(self): + pass + + def test_download_zip(self): + pass + + def test_download_cover(self): + pass \ No newline at end of file diff --git a/opds_catalog/tests/test_feeds.py b/opds_catalog/tests/test_feeds.py new file mode 100644 index 0000000000000000000000000000000000000000..ffa19d1d1c1d4333639b3305a0a59b38e7e0159a --- /dev/null +++ b/opds_catalog/tests/test_feeds.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- + +from django.core.urlresolvers import reverse +from django.test import TestCase, Client +from django.utils.translation import ugettext as _ + +from opds_catalog import settings + + +class feedsTestCase(TestCase): + fixtures = ['testdb.json'] + + def setUp(self): + settings.AUTH=False + + def test_MainFeed(self): + c = Client() + response = c.get('/opds/') + self.assertEquals(response.status_code, 200) + response = c.get(reverse('opds:main')); + self.assertEquals(response.status_code, 200) + self.assertIn(_('By catalogs'), response.content.decode()) + self.assertIn(_("Catalogs: %(catalogs)s, books: %(books)s.")%{"catalogs":2, "books":4}, response.content.decode()) + self.assertIn(_("Authors: %(authors)s.")%{"authors":4}, response.content.decode()) + self.assertIn(_("Genres: %(genres)s.")%{"genres":4}, response.content.decode()) + + def test_CatalogsFeed(self): + c = Client() + response = c.get('/opds/catalogs/') + self.assertEquals(response.status_code, 200) + response = c.get(reverse('opds:catalogs')); + self.assertEquals(response.status_code, 200) + self.assertIn('books.zip', response.content.decode()) + self.assertIn('The Sanctuary Sparrow', response.content.decode()) + + def test_CatalogsFeedTree(self): + c = Client() + response = c.get('/opds/catalogs/12/') + self.assertEquals(response.status_code, 200) + response = c.get( reverse('opds:cat_tree',args=['12']) ) + self.assertEquals(response.status_code, 200) + self.assertIn('Драконьи Услуги', response.content.decode()) + self.assertIn('Китайски сладкиш с късметче', response.content.decode()) + self.assertIn('Любовь в жизни Обломова', response.content.decode()) + + def test_OpenSearch(self): + c = Client() + response = c.get('/opds/search/') + self.assertEquals(response.status_code, 200) + self.assertIn('www.sopds.ru', response.content.decode()) + + def test_SearchTypes(self): + c = Client() + response = c.get('/opds/search/Драк/') + self.assertEquals(response.status_code, 200) + response = c.get(reverse('opds:searchtypes', kwargs={'searchterms':'Драк'})) + self.assertEquals(response.status_code, 200) + self.assertIn(_("Search by titles"), response.content.decode()) + + def test_SearchBooks(self): + c = Client() + response = c.get('/opds/search/books/m/Драк/') + self.assertEquals(response.status_code, 200) + response = c.get(reverse('opds:searchbooks', kwargs={'searchtype':'m','searchterms':'рак'})) + self.assertEquals(response.status_code, 200) + self.assertIn("Драконьи Услуги", response.content.decode()) + self.assertIn("Куприянов Денис", response.content.decode()) + response = c.get(reverse('opds:searchbooks', kwargs={'searchtype':'b','searchterms':'Драк'})) + self.assertEquals(response.status_code, 200) + self.assertIn("Драконьи Услуги", response.content.decode()) + self.assertIn("Куприянов Денис", response.content.decode()) + response = c.get(reverse('opds:searchbooks', kwargs={'searchtype':'a','searchterms':'1034'})) + self.assertEquals(response.status_code, 200) + self.assertIn("Драконьи Услуги", response.content.decode()) + self.assertIn("Куприянов Денис", response.content.decode()) + self.assertIn(_("All books by %(last_name)s %(first_name)s")%{"last_name":"Куприянов", "first_name":"Денис"}, response.content.decode()) + self.assertIn("prose_contemporary", response.content.decode()) + self.assertIn("T", response.content.decode()) + + def test_AuthorsFeed(self): + c = Client() + response = c.get('/opds/authors/0/') + self.assertEquals(response.status_code, 200) + if settings.ALPHABET_MENU: + response = c.get(reverse('opds:lang_authors')); + self.assertEquals(response.status_code, 200) + self.assertIn(_("Cyrillic"), response.content.decode()) + response = c.get(reverse('opds:char_authors', kwargs={'lang_code':0})); + self.assertIn("P", response.content.decode()) + + + def test_GenresFeed(self): + c = Client() + response = c.get('/opds/genres/') + self.assertEquals(response.status_code, 200) + response = c.get(reverse('opds:genres')); + self.assertEquals(response.status_code, 200) + self.assertIn("Неизвестный жанр", response.content.decode()) + response = c.get(reverse('opds:genres', kwargs={'section':266})); + self.assertEquals(response.status_code, 200) + self.assertIn("prose_contemporary", response.content.decode()) diff --git a/opds_catalog/tests/test_models.py b/opds_catalog/tests/test_models.py new file mode 100644 index 0000000000000000000000000000000000000000..b1fee154ef8ec12463844ae6a917fae6a23b1715 --- /dev/null +++ b/opds_catalog/tests/test_models.py @@ -0,0 +1,87 @@ +from datetime import datetime + +from django.test import TestCase +from django.utils import timezone +from django.contrib.auth.models import User +from django.conf import settings + +from opds_catalog.models import Book, Catalog, Author, Genre, Series, bookshelf, Counter, bauthor, bgenre, bseries +from opds_catalog import models +from opds_catalog import opdsdb + +class modelsTestCase(TestCase): + testdatetime = datetime(2016, 1, 1, 0, 0) + if settings.USE_TZ: + testdatetime = testdatetime.replace(tzinfo=timezone.get_current_timezone()) + + def setUp(self): + opdsdb.clear_all() + book = Book.objects.create(filename="testbook.fb2", path=".", filesize=500, format="fb2", cat_type=0, registerdate=self.testdatetime, + docdate="01.01.2016", lang="ru", title="Книга", annotation="Аннотация", avail=2, + catalog=Catalog.objects.create(parent=None, cat_name=".", path=".", cat_type=0) + ) + author = Author.objects.create(first_name="Дмитрий", last_name="Шелепнев") + genre = Genre.objects.create(genre="fantastic0", section="fantastic1", subsection="fantastic2") + series = Series.objects.create(ser="mywork") + bauthor.objects.create(book=book, author=author) + bgenre.objects.create(book=book, genre=genre) + bseries.objects.create(book=book, ser=series, ser_no=1) + user = User.objects.create_user("testuser","testuser@sopds.ru", "testpassword", first_name="Test", last_name="User") + bookshelf.objects.create(user=user, book=book, readtime=self.testdatetime) + Counter.objects.update_known_counters() + + + def test_Book(self): + """ Тестирование соответствия структуры модели Book и работоспособности БД """ + book = Book.objects.get(title="Книга") + self.assertEqual(book.filename, "testbook.fb2") + self.assertEqual(book.path, ".") + self.assertEqual(book.filesize, 500) + self.assertEqual(book.format, "fb2") + self.assertEqual(book.cat_type, 0) + self.assertEqual(book.registerdate, self.testdatetime) + self.assertEqual(book.docdate, "01.01.2016") + self.assertEqual(book.lang, "ru") + self.assertEqual(book.title, "Книга") + self.assertEqual(book.annotation, "Аннотация") + self.assertEqual(book.avail, 2) + self.assertEqual(book.catalog.path, ".") + self.assertEqual(book.catalog.cat_name, ".") + self.assertEqual(book.catalog.cat_type, 0) + + def test_Author(self): + """ Тестирование соответствия структуры моделей Author и bauthor и работоспособности БД """ + book = Book.objects.get(title="Книга") + self.assertEqual(book.authors.count(), 1) + self.assertEqual(book.authors.get(last_name="Шелепнев").first_name, "Дмитрий") + + + def test_Genre(self): + """ Тестирование соответствия структуры моделей Genre и bgenre и работоспособности БД """ + book = Book.objects.get(title="Книга") + self.assertEqual(book.genres.count(), 1) + self.assertEqual(book.genres.get(genre="fantastic0").section, "fantastic1") + self.assertEqual(book.genres.get(genre="fantastic0").subsection, "fantastic2") + + def test_Series(self): + """ Тестирование соответствия структуры моделей Series и bseries и работоспособности БД """ + book = Book.objects.get(title="Книга") + self.assertEqual(book.series.count(), 1) + ser = book.series.all()[0] + self.assertEqual(ser.ser,"mywork") + self.assertEqual(bseries.objects.get(ser=ser).ser_no, 1) + + def test_bookshelf(self): + """ Тестирование соответствия структуры модели bookshelf и работоспособности БД """ + user = User.objects.get(username="testuser") + self.assertEqual(bookshelf.objects.all().count(), 1) + self.assertEqual(bookshelf.objects.filter(user=user).count(), 1) + self.assertEqual(bookshelf.objects.get(user=user).book.title, "Книга") + + def test_Counter(self): + """ Тестирование соответствия структуры модели Counter, менеджера CounterManager и работоспособности БД """ + self.assertEqual(Counter.objects.get_counter(models.counter_allbooks), 1) + self.assertEqual(Counter.objects.get_counter(models.counter_allauthors), 1) + self.assertEqual(Counter.objects.get_counter(models.counter_allcatalogs), 1) + self.assertEqual(Counter.objects.get_counter(models.counter_allgenres), 1) + self.assertEqual(Counter.objects.get_counter(models.counter_allseries), 1) diff --git a/opds_catalog/tests/test_opdsdb.py b/opds_catalog/tests/test_opdsdb.py new file mode 100644 index 0000000000000000000000000000000000000000..e56f5e6d0e7b8feadafbc899b0e5d463b7a4e5e6 --- /dev/null +++ b/opds_catalog/tests/test_opdsdb.py @@ -0,0 +1,73 @@ +from django.test import TestCase +from opds_catalog.models import Catalog, bseries + +from opds_catalog import opdsdb + +class opdsdbTestCase(TestCase): + + def setUp(self): + opdsdb.clear_all() + opdsdb.addcattree("root/child/subchild",opdsdb.CAT_NORMAL) + book = opdsdb.addbook("testbook.fb2", "root/child",opdsdb.findcat("root/child"),".fb2","Test Book", "Annotation", "01.01.2016", "ru", 500, 0) + opdsdb.addbauthor(book, opdsdb.addauthor("Test","Author")) + opdsdb.addbgenre(book, opdsdb.addgenre("fantastic")) + opdsdb.addbseries(book, opdsdb.addseries("mywork"), 1) + + + def test_cat_fn(self): + """ Тестирование функций addcattree, findcat """ + self.assertEqual(Catalog.objects.filter(parent=None).count(), 1) + self.assertEqual(Catalog.objects.all().count(), 4) + + cat = Catalog.objects.get(parent=None) + self.assertEqual(cat.cat_name,".") + cat = Catalog.objects.get(parent=cat) + self.assertEqual(cat.cat_name, "root") + cat = Catalog.objects.get(parent=cat) + self.assertEqual(cat.cat_name, "child") + cat = Catalog.objects.get(parent=cat) + self.assertEqual(cat.cat_name, "subchild") + + cat = opdsdb.findcat("root/child") + self.assertEqual(cat.cat_name, "child") + self.assertEqual(cat.path, "root/child") + self.assertEqual(cat.parent.cat_name, "root") + self.assertEqual(cat.parent.parent.cat_name, ".") + self.assertIsNone(cat.parent.parent.parent) + + def test_book_fn(self): + """ Тестирование функций addbook, findbook """ + book = opdsdb.findbook("testbook.fb2","root/child") + self.assertIsNotNone(book) + self.assertEqual(book.filename,"testbook.fb2") + self.assertEqual(book.path, "root/child") + self.assertEqual(book.catalog.cat_name, "child") + self.assertEqual(book.catalog.cat_type, 0) + self.assertEqual(book.format, "fb2") + self.assertEqual(book.title, "Test Book") + self.assertEqual(book.annotation, "Annotation") + self.assertEqual(book.docdate, "01.01.2016") + self.assertEqual(book.lang, "ru") + self.assertEqual(book.filesize, 500) + self.assertEqual(book.cat_type, 0) + + def test_author_fn(self): + """ Тестирование функций addauthor, addbauthor """ + book = opdsdb.findbook("testbook.fb2", "root/child") + self.assertEqual(book.authors.count(), 1) + self.assertEqual(book.authors.get(last_name="Author").first_name, "Test") + + def test_genre_fn(self): + """ Тестирование функций addgenre, addbgenre """ + book = opdsdb.findbook("testbook.fb2", "root/child") + self.assertEqual(book.genres.count(), 1) + self.assertEqual(book.genres.get(genre="fantastic").section, opdsdb.unknown_genre) + self.assertEqual(book.genres.get(genre="fantastic").subsection, "fantastic") + + def test_series_fn(self): + """ Тестирование функций addseries, addbseries """ + book = opdsdb.findbook("testbook.fb2", "root/child") + self.assertEqual(book.series.count(), 1) + ser = book.series.all()[0] + self.assertEqual(ser.ser, "mywork") + self.assertEqual(bseries.objects.get(ser=ser).ser_no, 1) \ No newline at end of file diff --git a/opds_catalog/tests/test_parsers.py b/opds_catalog/tests/test_parsers.py new file mode 100644 index 0000000000000000000000000000000000000000..27bbbc457eff2974c56563ee0aa4395074319ba6 --- /dev/null +++ b/opds_catalog/tests/test_parsers.py @@ -0,0 +1,46 @@ +import os + +from django.test import TestCase + +from opds_catalog.fb2parse import fb2parser + +class parserTestCase(TestCase): + test_module_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + test_ROOTLIB = os.path.join(test_module_path, 'tests/data') + test_fb2 = "262001.fb2" + test_bad_fb2 = "badfile.fb2" + + def setUp(self): + pass + + def test_fb2parse_valid(self): + """ Тестирование класса fb2parser - разбор валидного fb2 """ + parser = fb2parser() + parser.reset() + f = open(os.path.join(self.test_ROOTLIB, self.test_fb2), 'rb') + parser.parse(f) + self.assertEquals(parser.book_title.getvalue()[0], "The Sanctuary Sparrow") + self.assertEquals(parser.author_first.getvalue()[0], "Ellis") + self.assertEquals(parser.author_last.getvalue()[0], "Peters") + self.assertEquals(parser.genre.getvalue()[0], "antique") + self.assertEquals(parser.lang.getvalue()[0], "en") + self.assertEquals(parser.docdate.getvalue()[0], "30.1.2011") + self.assertEquals(parser.parse_error, 0) + + def test_fb2parse_novalid(self): + """ Тестирование класса fb2parser - разбор невалидного fb2 """ + parser = fb2parser() + parser.reset() + f = open(os.path.join(self.test_ROOTLIB, self.test_bad_fb2), 'rb') + parser.parse(f) + self.assertNotEquals(parser.parse_error, 0) + + def test_fb2parse_cover(self): + """ Тестирование класса fb2parser - извлечение обдложки из fb2 """ + parser = fb2parser(True) + parser.reset() + f = open(os.path.join(self.test_ROOTLIB, self.test_fb2), 'rb') + parser.parse(f) + self.assertEquals(parser.parse_error, 0) + self.assertEquals(len(parser.cover_image.cover_data), 76207) + self.assertEquals(parser.cover_image.getattr('content-type'), "image/jpeg") diff --git a/opds_catalog/tests/test_scan.py b/opds_catalog/tests/test_scan.py new file mode 100644 index 0000000000000000000000000000000000000000..87a3395731cf136469d0e148c8cdf27093c1fd71 --- /dev/null +++ b/opds_catalog/tests/test_scan.py @@ -0,0 +1,99 @@ +import os + +from django.test import TestCase + +from opds_catalog import opdsdb +from opds_catalog.sopdscan import opdsScanner +from opds_catalog import settings +from opds_catalog.models import Book, Catalog, Author, Genre, Series + +class scanTestCase(TestCase): + test_module_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + test_ROOTLIB = os.path.join(test_module_path, 'tests/data') + test_fb2 = "262001.fb2" + test_zip = "books.zip" + + def setUp(self): + settings.ROOT_LIB = self.test_ROOTLIB + + def test_processfile(self): + """ Тестирование процедуры processfile (извлекает метаданные из книги и помещает в БД) """ + opdsdb.clear_all() + scanner = opdsScanner() + scanner.processfile(self.test_fb2, self.test_ROOTLIB, os.path.join(self.test_ROOTLIB,self.test_fb2), None,0,495373) + book = Book.objects.get(filename=self.test_fb2) + self.assertIsNotNone(book) + self.assertEqual(scanner.books_added,1) + self.assertEqual(book.filename, self.test_fb2) + self.assertEqual(book.path, ".") + self.assertEqual(book.format, "fb2") + self.assertEqual(book.cat_type, 0) + #self.assertGreaterEqual(book.registerdate, ) + self.assertEqual(book.docdate, "30.1.2011") + self.assertEqual(book.lang, "en") + self.assertEqual(book.title, "The Sanctuary Sparrow") + self.assertEqual(book.annotation, "") + self.assertEqual(book.avail, 2) + self.assertEqual(book.catalog.path, ".") + self.assertEqual(book.catalog.cat_name, ".") + self.assertEqual(book.catalog.cat_type, 0) + self.assertEqual(book.filesize, 495373) + + self.assertEqual(book.authors.count(), 1) + self.assertEqual(book.authors.get(last_name="Peters").first_name, "Ellis") + + self.assertEqual(book.genres.count(), 1) + self.assertEqual(book.genres.get(genre="antique").section, opdsdb.unknown_genre) + self.assertEqual(book.genres.get(genre="antique").subsection, "antique") + + def test_processzip(self): + """ Тестирование процедуры processzip (извлекает метаданные из книг, помещенных в архив и помещает их БД) """ + opdsdb.clear_all() + scanner = opdsScanner() + scanner.processzip(self.test_zip, self.test_ROOTLIB, os.path.join(self.test_ROOTLIB,self.test_zip) ) + self.assertEquals(scanner.books_added, 3) + self.assertEquals(Book.objects.all().count(), 3) + self.assertEquals(Catalog.objects.all().count(), 2) + + book = Book.objects.get(filename="539603.fb2") + self.assertEqual(book.filesize, 15194) + self.assertEqual(book.path, self.test_zip) + self.assertEqual(book.cat_type, 1) + self.assertEqual(book.catalog.path, self.test_zip) + self.assertEqual(book.catalog.cat_name, self.test_zip) + self.assertEqual(book.catalog.cat_type, 1) + self.assertEqual(book.docdate, "130552595662030000") + self.assertEqual(book.title, "Любовь в жизни Обломова") + self.assertEqual(book.avail, 2) + self.assertEqual(book.authors.count(), 1) + self.assertEqual(book.authors.get(last_name="Логинов").first_name, "Святослав") + self.assertEqual(book.genres.count(), 1) + self.assertEqual(book.genres.get(genre="nonf_criticism").section, opdsdb.unknown_genre) + self.assertEqual(book.genres.get(genre="nonf_criticism").subsection, "nonf_criticism") + + book = Book.objects.get(filename="539485.fb2") + self.assertEqual(book.filesize, 12293) + self.assertEqual(book.path, self.test_zip) + self.assertEqual(book.cat_type, 1) + self.assertEqual(book.title, "Китайски сладкиш с късметче") + self.assertEqual(book.authors.get(last_name="Фрич").first_name, "Чарлз") + + book = Book.objects.get(filename="539273.fb2") + self.assertEqual(book.filesize, 21722) + self.assertEqual(book.path, self.test_zip) + self.assertEqual(book.cat_type, 1) + self.assertEqual(book.title, "Драконьи Услуги") + self.assertEqual(book.authors.get(last_name="Куприянов").first_name, "Денис") + + def test_scanall(self): + """ Тестирование процедуры scanall (извлекает метаданные из книг и помещает в БД) """ + opdsdb.clear_all() + scanner = opdsScanner() + scanner.scan_all() + self.assertEquals(scanner.books_added, 4) + self.assertEquals(scanner.bad_books, 1) + self.assertEquals(Book.objects.all().count(), 4) + self.assertEquals(Author.objects.all().count(), 4) + self.assertEquals(Genre.objects.all().count(), 4) + self.assertEquals(Series.objects.all().count(), 0) + self.assertEquals(Catalog.objects.all().count(), 2) diff --git a/opds_catalog/tests/test_zipf.py b/opds_catalog/tests/test_zipf.py new file mode 100644 index 0000000000000000000000000000000000000000..67670448ce75d2544e3492f4d3a014a93ceaf875 --- /dev/null +++ b/opds_catalog/tests/test_zipf.py @@ -0,0 +1,36 @@ +import os + +from django.test import TestCase + +from opds_catalog import zipf as zipfile + +class zipTestCase(TestCase): + test_module_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + test_ROOTLIB = os.path.join(test_module_path, 'tests/data') + test_zip = "books.zip" + test_bad_zip = "badfile.zip" + + def setUp(self): + pass + + def test_zip_valid(self): + z = zipfile.ZipFile(os.path.join(self.test_ROOTLIB, self.test_zip), 'r', allowZip64=True) + filelist = z.namelist() + file_size = z.getinfo("539485.fb2").file_size + file = z.open("539485.fb2") + self.assertListEqual(filelist,["539603.fb2","539485.fb2","539273.fb2"]) + self.assertEquals(file_size,12293) + self.assertEquals(file.read(38), b'') + file.close() + + + def test_zip_novalid(self): + bad_file_count = 0 + try: + zipfile.ZipFile(os.path.join(self.test_ROOTLIB, self.test_bad_zip), 'r', allowZip64=True) + except zipfile.BadZipFile: + bad_file_count = 1 + + self.assertEquals(bad_file_count, 1) + + diff --git a/opds_catalog/tmp/emptyfile b/opds_catalog/tmp/emptyfile new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opds_catalog/urls.py b/opds_catalog/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..94a472392068f5576f9d315853f4188b7bcf015f --- /dev/null +++ b/opds_catalog/urls.py @@ -0,0 +1,50 @@ + +from django.conf.urls import url +from opds_catalog import feeds, dl + +urlpatterns = [ + url(r'^catalogs/$',feeds.CatalogsFeed(), name='catalogs'), + url(r'^catalogs/(?P[0-9]+)/$',feeds.CatalogsFeed(), name='cat_tree'), + url(r'^catalogs/(?P[0-9]+)/(?P[0-9]+)/$',feeds.CatalogsFeed(), name='cat_page'), + + url(r'^books/$',feeds.LangFeed(), name='lang_books'), + url(r'^books/0/$',feeds.BooksFeed(), name='nolang_books'), + url(r'^books/(?P[0-9])/$',feeds.BooksFeed(), name='char_books'), + url(r'^books/(?P[0-9])/(?P.+)/$',feeds.BooksFeed(), name='chars_books'), + + url(r'^authors/$',feeds.LangFeed(), name='lang_authors'), + url(r'^authors/0/$',feeds.AuthorsFeed(), name='nolang_authors'), + url(r'^authors/(?P[0-9])/$',feeds.AuthorsFeed(), name='char_authors'), + url(r'^authors/(?P[0-9])/(?P.+)/$',feeds.AuthorsFeed(), name='chars_authors'), + + url(r'^series/$',feeds.LangFeed(), name='lang_series'), + url(r'^series/0/$',feeds.SeriesFeed(), name='nolang_series'), + url(r'^series/(?P[0-9])/$',feeds.SeriesFeed(), name='char_series'), + url(r'^series/(?P[0-9])/(?P.+)/$',feeds.SeriesFeed(), name='chars_series'), + + url(r'^genres/$',feeds.GenresFeed(), name='genres'), + url(r'^genres/(?P
\d+)/$',feeds.GenresFeed(), name='genres'), + + url(r'^search/$',feeds.OpenSearch, name='opensearch'), + + url(r'^search/books/(?P[bmasgued])/(?P.+)/(?P\d+)/',feeds.SearchBooksFeed(), name='searchbooks'), + url(r'^search/books/(?P[bmasgued])/(?P.+)/',feeds.SearchBooksFeed(), name='searchbooks'), + url(r'^search/books/(?Pas)/(?P.+)/(?P.+)/(?P\d+)/',feeds.SearchBooksFeed(), name='searchbooks'), + url(r'^search/books/(?Pas)/(?P.+)/(?P.+)/',feeds.SearchBooksFeed(), name='searchbooks'), + url(r'^search/books/(?Pas)/(?P.+)/',feeds.SelectSeriesFeed(), name='searchbooks'), + url(r'^search/books/u/0/',feeds.SearchBooksFeed(), name='bookshelf'), + + url(r'^search/authors/(?P[bme])/(?P.+)/(?P\d+)/',feeds.SearchAuthorsFeed(), name='searchauthors'), + url(r'^search/authors/(?P[bme])/(?P.+)/',feeds.SearchAuthorsFeed(), name='searchauthors'), + + url(r'^search/series/(?P[bmae])/(?P.+)/(?P\d+)/',feeds.SearchSeriesFeed(), name='searchseries'), + url(r'^search/series/(?P[bmae])/(?P.+)/',feeds.SearchSeriesFeed(), name='searchseries'), + + url(r'^search/(?P.+)/',feeds.SearchTypesFeed(), name='searchtypes'), + + url(r'^convert/(?P[0-9]+)/(?P.+)/$',dl.ConvertFB2, name='convert'), + url(r'^download/(?P[0-9]+)/(?P[0-1])/$',dl.Download, name='download'), + url(r'^cover/(?P[0-9]+)/$',dl.Cover, name='cover'), + + url(r'^',feeds.MainFeed(), name='main'), +] diff --git a/opds_catalog/utils.py b/opds_catalog/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..5f5cd7238254f8ec20910ee539a987de5c9f495e --- /dev/null +++ b/opds_catalog/utils.py @@ -0,0 +1,13 @@ +####################################################################### +# +# Вспомогательные функции +# +def translit(s): + """Russian translit: converts 'привет'->'privet'""" + assert s is not str, "Error: argument MUST be string" + + table1 = str.maketrans("абвгдеёзийклмнопрстуфхъыьэАБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЬЭ", "abvgdeezijklmnoprstufh'y'eABVGDEEZIJKLMNOPRSTUFH'Y'E") + table2 = {'ж':'zh','ц':'ts','ч':'ch','ш':'sh','щ':'sch','ю':'ju','я':'ja', 'Ж':'Zh','Ц':'Ts','Ч':'Ch','Ш':'Sh','Щ':'Sch','Ю':'Ju','Я':'Ja', '«':'\'', '»':'\'','"':'\'','\n':' '} + for k in table2.keys(): + s = s.replace(k,table2[k]) + return s.translate(table1) \ No newline at end of file diff --git a/opds_catalog/views.py b/opds_catalog/views.py new file mode 100644 index 0000000000000000000000000000000000000000..2536b376efd02b2fa61e25f2dfa2552042caf0b8 --- /dev/null +++ b/opds_catalog/views.py @@ -0,0 +1 @@ +from django.shortcuts import render diff --git a/py/zipf.py b/opds_catalog/zipf.py similarity index 100% rename from py/zipf.py rename to opds_catalog/zipf.py diff --git a/py/__pycache__/sopdscfg.cpython-33.pyc b/py/__pycache__/sopdscfg.cpython-33.pyc deleted file mode 100644 index e9a0e2f283c22d06b83898e8c01e0757ea78cab6..0000000000000000000000000000000000000000 Binary files a/py/__pycache__/sopdscfg.cpython-33.pyc and /dev/null differ diff --git a/py/__pycache__/sopdsdb.cpython-33.pyc b/py/__pycache__/sopdsdb.cpython-33.pyc deleted file mode 100644 index 63885f7b242e575ae26f346d2f551385b4bd8d97..0000000000000000000000000000000000000000 Binary files a/py/__pycache__/sopdsdb.cpython-33.pyc and /dev/null differ diff --git a/py/__pycache__/sopdsparse.cpython-33.pyc b/py/__pycache__/sopdsparse.cpython-33.pyc deleted file mode 100644 index d83dabf3e4cf609c0448ebdce6d1b51729aa1cba..0000000000000000000000000000000000000000 Binary files a/py/__pycache__/sopdsparse.cpython-33.pyc and /dev/null differ diff --git a/py/fb2parse.py b/py/fb2parse.py deleted file mode 100755 index 82efb9e6a5bf25768561e92727b7416df08234c8..0000000000000000000000000000000000000000 --- a/py/fb2parse.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import sopdsparse -import base64 - -f=open('105863.fb2','rb') -parser=sopdsparse.fb2parser(True) -parser.parse(f) -print("Errorstr= ",parser.parse_errormsg) -print(parser.author_first.getvalue(), parser.author_last.getvalue(), parser.genre.getvalue(), parser.lang.getvalue(), parser.book_title.getvalue()) -print(parser.annotation.getvalue()) -i=0 -print(parser.cover_image.cover_data) -jpg=open('image.jpg','wb') -sstr=parser.cover_image.cover_data.strip("' ") -dstr=base64.b64decode(sstr) -jpg.write(dstr) -jpg.close() -print(parser.cover_image.cover_data) -print(parser.cover_image.cover_name) -print(parser.cover_image.getattr('content-type')) -f.close() - diff --git a/py/nocover.jpg b/py/nocover.jpg deleted file mode 100644 index 6fbcbb70d0a72c81beb826769f24fe0cadb9043a..0000000000000000000000000000000000000000 Binary files a/py/nocover.jpg and /dev/null differ diff --git a/py/sopds-scan.py b/py/sopds-scan.py deleted file mode 100755 index cbcd59777aa86f0e85902b88e35b1b8f54bb751d..0000000000000000000000000000000000000000 --- a/py/sopds-scan.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import logging -import sopdscfg -from sopdscan import opdsScanner -from optparse import OptionParser -from sys import argv - -if (__name__=="__main__"): - parser=OptionParser(conflict_handler="resolve", version="sopds-scan.py. Version "+sopdscfg.VERSION, add_help_option=True, usage='sopds-scan.py [options]',description='sopds-scan.py: Simple OPDS Scanner - programm for scan your e-books directory and store data to MYSQL database.') - parser.add_option('-v','--verbose', action='store_true', dest='verbose', default=False, help='Enable verbose output') - parser.add_option('-c','--config',dest='configfile',default='',help='Config file pargh') - (options,arguments)=parser.parse_args() - VERBOSE=options.verbose - CFG_FILE=options.configfile - - if CFG_FILE=='': cfg=sopdscfg.cfgreader() - else: cfg=sopdscfg.cfgreader(CFG_FILE) - - logger = logging.getLogger('') - logger.setLevel(logging.DEBUG) - formatter=logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') - - if cfg.LOGLEVEL!=logging.NOTSET: - # Создаем обработчик для записи логов в файл - fh = logging.FileHandler(cfg.LOGFILE) - fh.setLevel(cfg.LOGLEVEL) - fh.setFormatter(formatter) - logger.addHandler(fh) - - if VERBOSE: - # Создадим обработчик для вывода логов на экран с максимальным уровнем вывода - ch = logging.StreamHandler() - ch.setLevel(logging.DEBUG) - ch.setFormatter(formatter) - logger.addHandler(ch) - - scanner=opdsScanner(cfg,logger) - scanner.scan_all() - diff --git a/py/sopds.cgi b/py/sopds.cgi deleted file mode 100755 index eed6a04c2fce312f50725b9f4b9477f671a230b5..0000000000000000000000000000000000000000 --- a/py/sopds.cgi +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import sys -import sopdscfg -import sopdscli -import os -import zipf - -if (__name__=="__main__"): - cfg=sopdscfg.cfgreader() - zipf.ZIP_CODEPAGE=cfg.ZIP_CODEPAGE - - user = None - if 'REMOTE_USER' in os.environ: - user = os.environ['REMOTE_USER'] - - sopds = sopdscli.opdsClient(cfg) - sopds.resetParams() - sopds.parseParams(os.environ) - sopds.setUser(user) - sopds.make_response() - sopds.write_response_headers() - sopds.write_response() - diff --git a/py/sopds.wsgi b/py/sopds.wsgi deleted file mode 100755 index e2f412003b2797778ee746e4fbc66d8d4cd30da6..0000000000000000000000000000000000000000 --- a/py/sopds.wsgi +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import sys -import os - -PY_PATH=os.path.dirname(os.path.abspath(__file__)) -sys.path.append(PY_PATH) - -import sopdscli -import sopdscfg -import zipf - -cfg=sopdscfg.cfgreader() -zipf.ZIP_CODEPAGE=cfg.ZIP_CODEPAGE - -def app(environ, start_response): - user = None - if 'REMOTE_USER' in environ: - user = environ['REMOTE_USER'] - - sopds = sopdscli.opdsClient(cfg,sopdscli.modeWSGI) - sopds.resetParams() - sopds.parseParams(environ) - sopds.setUser(user) - sopds.make_response() - start_response(sopds.get_response_status(), sopds.get_response_headers()) - return sopds.get_response_body() - -application = app diff --git a/py/sopdscan.py b/py/sopdscan.py deleted file mode 100644 index 2899ecfd8ed8bf1da3521cc35443acc442e33bab..0000000000000000000000000000000000000000 --- a/py/sopdscan.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import os -import sopdsdb -import sopdsparse -import time -import datetime -import sopdscfg -import base64 -import zipf -import logging - -class opdsScanner: - def __init__(self, cfg, logger): - self.cfg=cfg - self.logger=logger - self.opdsdb=None - self.fb2parser=None - self.init_parser() - zipf.ZIP_CODEPAGE=self.cfg.ZIP_CODEPAGE - self.extensions_set={x for x in self.cfg.EXT_LIST} - - def init_stats(self): - self.t1=datetime.timedelta(seconds=time.time()) - self.t2=self.t1 - self.t3=self.t1 - self.books_added = 0 - self.books_skipped = 0 - self.books_deleted = 0 - self.arch_scanned = 0 - self.arch_skipped = 0 - self.bad_archives = 0 - self.books_in_archives = 0 - - def init_parser(self): - self.fb2parser=sopdsparse.fb2parser(False) - - def log_options(self): - self.logger.info(' ***** Starting sopds-scan...') - self.logger.debug('OPTIONS SET') - if self.cfg.CONFIGFILE!=None: self.logger.debug('configfile = '+self.cfg.CONFIGFILE) - if self.cfg.ROOT_LIB!=None: self.logger.debug('root_lib = '+self.cfg.ROOT_LIB) - if self.cfg.FB2TOEPUB_PATH!=None: self.logger.debug('fb2toepub = '+self.cfg.FB2TOEPUB_PATH) - if self.cfg.FB2TOMOBI_PATH!=None: self.logger.debug('fb2tomobi = '+self.cfg.FB2TOMOBI_PATH) - if self.cfg.TEMP_DIR!=None: self.logger.debug('temp_dir = '+self.cfg.TEMP_DIR) - - def log_stats(self): - self.t2=datetime.timedelta(seconds=time.time()) - self.logger.info('Books added : '+str(self.books_added)) - self.logger.info('Books skipped : '+str(self.books_skipped)) - if self.cfg.DELETE_LOGICAL: - self.logger.info('Books deleted : '+str(self.books_deleted)) - else: - self.logger.info('Books DB entries deleted : '+str(self.books_deleted)) - self.logger.info('Books in archives: '+str(self.books_in_archives)) - self.logger.info('Archives scanned : '+str(self.arch_scanned)) - self.logger.info('Archives skipped : '+str(self.arch_skipped)) - self.logger.info('Bad archives : '+str(self.bad_archives)) - - t=self.t2-self.t1 - seconds=t.seconds%60 - minutes=((t.seconds-seconds)//60)%60 - hours=t.seconds//3600 - self.logger.info('Time estimated:'+str(hours)+' hours, '+str(minutes)+' minutes, '+str(seconds)+' seconds.') - - def log_stats_dbl(self): - self.t3=datetime.timedelta(seconds=time.time()) - t=self.t3-self.t2 - seconds=t.seconds%60 - minutes=((t.seconds-seconds)//60)%60 - hours=t.seconds//3600 - self.logger.info('Finishing mark_double proc in '+str(hours)+' hours, '+str(minutes)+' minutes, '+str(seconds)+' seconds.') - - def scan_all(self): - self.init_stats() - self.log_options() - self.opdsdb=sopdsdb.opdsDatabase(self.cfg.DB_NAME,self.cfg.DB_USER,self.cfg.DB_PASS,self.cfg.DB_HOST,self.cfg.ROOT_LIB) - self.opdsdb.openDB() - self.opdsdb.avail_check_prepare() - - for full_path, dirs, files in os.walk(self.cfg.ROOT_LIB, followlinks=True): - for name in files: - file=os.path.join(full_path,name) - (n,e)=os.path.splitext(name) - if (e.lower() == '.zip'): - if self.cfg.ZIPSCAN: - self.processzip(name,full_path,file) - else: - file_size=os.path.getsize(file) - self.processfile(name,full_path,file,0,file_size) - - self.opdsdb.commit() - if self.cfg.DELETE_LOGICAL: - self.books_deleted=self.opdsdb.books_del_logical() - else: - self.books_deleted=self.opdsdb.books_del_phisical() - self.log_stats() - - if self.cfg.DUBLICATES_FIND!=0: - self.logger.info('Starting mark_double proc with DUBLICATES_FIND param = %s'%self.cfg.DUBLICATES_FIND) - self.opdsdb.mark_double(self.cfg.DUBLICATES_FIND) - self.log_stats_dbl() - - self.opdsdb.closeDB() - self.opdsdb=None - - def processzip(self,name,full_path,file): - rel_file=os.path.relpath(file,self.cfg.ROOT_LIB) - if self.cfg.ZIPRESCAN or self.opdsdb.zipisscanned(rel_file,1)==0: - cat_id=self.opdsdb.addcattree(rel_file,1) - try: - z = zipf.ZipFile(file, 'r', allowZip64=True) - filelist = z.namelist() - for n in filelist: - try: - self.logger.debug('Start process ZIP file = '+file+' book file = '+n) - file_size=z.getinfo(n).file_size - self.processfile(n,file,z.open(n),1,file_size,cat_id=cat_id) - except: - self.logger.error('Error processing ZIP file = '+file+' book file = '+n) - z.close() - self.arch_scanned+=1 - except: - self.logger.error('Error while read ZIP archive. File '+file+' corrupt.') - self.bad_archives+=1 - else: - self.arch_skipped+=1 - self.logger.debug('Skip ZIP archive '+rel_file+'. Already scanned.') - - def processfile(self,name,full_path,file,archive=0,file_size=0,cat_id=0): - (n,e)=os.path.splitext(name) - if e.lower() in self.extensions_set: - rel_path=os.path.relpath(full_path,self.cfg.ROOT_LIB) - self.logger.debug("Attempt to add book "+rel_path+"/"+name) - self.fb2parser.reset() - if self.opdsdb.findbook(name,rel_path,1)==0: - if archive==0: - cat_id=self.opdsdb.addcattree(rel_path,archive) - title='' - lang='' - annotation='' - docdate='' - - if e.lower()=='.fb2' and self.cfg.FB2PARSE: - if isinstance(file, str): - f=open(file,'rb') - else: - f=file - self.fb2parser.parse(f,self.cfg.FB2HSIZE) - f.close() - - if len(self.fb2parser.lang.getvalue())>0: - lang=self.fb2parser.lang.getvalue()[0].strip(' \'\"') - if len(self.fb2parser.book_title.getvalue())>0: - title=self.fb2parser.book_title.getvalue()[0].strip(' \'\"\&-.#\\\`') - if len(self.fb2parser.annotation.getvalue())>0: - annotation=('\n'.join(self.fb2parser.annotation.getvalue()))[:10000] - if len(self.fb2parser.docdate.getvalue())>0: - docdate=self.fb2parser.docdate.getvalue()[0].strip(); - - if self.fb2parser.parse_error!=0: -# errormsg=error.message(self.fb2parser.parse_errormsg.code) - errormsg='' - self.logger.warning(rel_path+' - '+name+' fb2 parse error ['+errormsg+']') - - if title=='': title=n - - book_id=self.opdsdb.addbook(name,rel_path,cat_id,e,title,annotation,docdate,lang,file_size,archive,self.cfg.DUBLICATES_FIND) - self.books_added+=1 - - if archive==1: - self.books_in_archives+=1 - self.logger.debug("Book "+rel_path+"/"+name+" Added ok.") - - idx=0 - for l in self.fb2parser.author_last.getvalue(): - last_name=l.strip(' \'\"\&-.#\\\`') - first_name=self.fb2parser.author_first.getvalue()[idx].strip(' \'\"\&-.#\\\`') - author_id=self.opdsdb.addauthor(first_name,last_name) - self.opdsdb.addbauthor(book_id,author_id) - idx+=1 - for l in self.fb2parser.genre.getvalue(): - self.opdsdb.addbgenre(book_id,self.opdsdb.addgenre(l.lower().strip(' \'\"'))) -# for l in self.fb2parser.series.getattrs('name'): -# self.opdsdb.addbseries(book_id,self.opdsdb.addseries(l.strip())) - for l in self.fb2parser.series.attrss: - ser_name=l.get('name') - if ser_name: - ser_id=self.opdsdb.addseries(ser_name.strip()) - sser_no=l.get('number','0').strip() - if sser_no.isdigit(): - ser_no=int(sser_no) - else: - ser_no=0 - self.opdsdb.addbseries(book_id,ser_id,ser_no) - - if not self.cfg.SINGLE_COMMIT: self.opdsdb.commit() - - else: - self.books_skipped+=1 - self.logger.debug("Book "+rel_path+"/"+name+" Already in DB.") diff --git a/py/sopdscfg.py b/py/sopdscfg.py deleted file mode 100644 index e8f7548c3b75be2b64df8e4efe87c83c0903be79..0000000000000000000000000000000000000000 --- a/py/sopdscfg.py +++ /dev/null @@ -1,184 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -import sys -import codecs -import logging - -########################################################################## -# Глобальные переменные -# -VERSION="0.23" -PY_PATH=os.path.dirname(os.path.abspath(__file__)) -(ROOT_PATH,tmp)=os.path.split(PY_PATH) -CFG_FILENAME='sopds.conf' -CFG_PATH_DEFAULT=ROOT_PATH+os.path.sep+'conf'+os.path.sep+CFG_FILENAME -CFG_PATH=CFG_PATH_DEFAULT -NOCOVER_IMG='nocover.jpg' -NOCOVER_PATH=os.path.join(PY_PATH,NOCOVER_IMG) -LOG_PATH=os.path.join(ROOT_PATH,'logs') - -loglevels={'debug':logging.DEBUG,'info':logging.INFO,'warning':logging.WARNING,'error':logging.ERROR,'critical':logging.CRITICAL,'none':logging.NOTSET} - -########################################################################### -# Считываем конфигурацию из конфигурационного файла -# используем модуль configparser -import configparser - -class ConfigParser_new(configparser.ConfigParser): - - def getdefault(self,section,value,default_value): - try: - result=self.get(section,value) - except: - result=default_value - return result - - def getdefault_bool(self,section,value,default_value): - try: - result=self.getboolean(section,value) - except: - result=default_value - return result - - def getdefault_int(self,section,value,default_value): - try: - strval=self.get(section,value) - if strval.isdigit(): result=int(strval) - else: result=default_value - except: - result=default_value - return result - - - -class cfgreader: - def __init__(self,configfile=CFG_PATH): - self.CONFIGFILE=configfile - self.parse() - - def parse(self): - config=ConfigParser_new() - config.readfp(codecs.open(self.CONFIGFILE,"r","utf-8")) - CFG_S_GLOBAL='global' - - self.CGI_PATH=config.getdefault(CFG_S_GLOBAL,'cgi_path','sopds.cgi') - self.CGI_PATH=os.path.normpath(self.CGI_PATH) - - self.WSGI_PATH=config.getdefault(CFG_S_GLOBAL,'wsgi_path','sopds.wsgi') - self.WSGI_PATH=os.path.normpath(self.WSGI_PATH) - - fb2toepub_path=config.getdefault(CFG_S_GLOBAL,'fb2toepub',None) - if fb2toepub_path: - self.FB2TOEPUB_PATH=os.path.normpath(os.path.join(PY_PATH,fb2toepub_path)) - else: - self.FB2TOEPUB_PATH=None - self.FB2TOEPUB=self.FB2TOEPUB_PATH!=None and os.path.isfile(self.FB2TOEPUB_PATH) - - fb2tomobi_path=config.getdefault(CFG_S_GLOBAL,'fb2tomobi',None) - if fb2tomobi_path: - self.FB2TOMOBI_PATH=os.path.normpath(os.path.join(PY_PATH,fb2tomobi_path)) - else: - self.FB2TOMOBI_PATH=None - self.FB2TOMOBI=self.FB2TOMOBI_PATH!=None and os.path.isfile(self.FB2TOMOBI_PATH) - - self.TEMP_DIR=config.getdefault(CFG_S_GLOBAL,'temp_dir','/tmp') - self.TEMP_DIR=os.path.normpath(self.TEMP_DIR) - - logfile=config.getdefault(CFG_S_GLOBAL,'logfile','scan.log') - self.LOGFILE=os.path.join(LOG_PATH,logfile) - loglevel=config.getdefault(CFG_S_GLOBAL,'loglevel','info') - if loglevel.lower() in loglevels: - self.LOGLEVEL=loglevels[loglevel.lower()] - else: - self.LOGLEVEL=logging.NOTSET - - self.DB_NAME=config.get(CFG_S_GLOBAL,'db_name') - self.DB_USER=config.get(CFG_S_GLOBAL,'db_user') - self.DB_PASS=config.get(CFG_S_GLOBAL,'db_pass') - self.DB_HOST=config.get(CFG_S_GLOBAL,'db_host') - self.DB_CHARSET=config.get(CFG_S_GLOBAL,'db_charset') - self.ROOT_LIB=os.path.abspath(config.get(CFG_S_GLOBAL,'root_lib')) - self.FORMATS=config.get(CFG_S_GLOBAL,'formats') - dublicates_find=config.getdefault(CFG_S_GLOBAL,'dublicates_find','yes').lower() - if dublicates_find=='yes': - self.DUBLICATES_FIND=1 - elif dublicates_find=='strong': - self.DUBLICATES_FIND=2 - elif dublicates_find=='clear': - self.DUBLICATES_FIND=3 - else: - self.DUBLICATES_FIND=0 - - self.DUBLICATES_SHOW=config.getboolean(CFG_S_GLOBAL,'dublicates_show') - self.FB2PARSE=config.getboolean(CFG_S_GLOBAL,'fb2parse') - self.ZIPSCAN=config.getboolean(CFG_S_GLOBAL,'zipscan') - self.ZIPRESCAN=config.getboolean(CFG_S_GLOBAL,'ziprescan') - self.DELETE_LOGICAL=config.getboolean(CFG_S_GLOBAL,'delete_logical') - self.ZIPFILE_PATCH=config.getdefault_bool(CFG_S_GLOBAL,'zipfile_patch',False) - self.SINGLE_COMMIT=config.getdefault_bool(CFG_S_GLOBAL,'single_commit',False) - self.TITLE_AS_FN=config.getdefault_bool(CFG_S_GLOBAL,'title_as_filename',False) - self.ALPHA=config.getdefault_bool(CFG_S_GLOBAL,'alphabet_menu',True) - self.FB2HSIZE=config.getdefault_int(CFG_S_GLOBAL,'fb2hsize',0) - self.MAXITEMS=config.getdefault_int(CFG_S_GLOBAL,'maxitems',50) - self.SPLITAUTHORS=config.getdefault_int(CFG_S_GLOBAL,'splitauthors',0) - self.SPLITTITLES=config.getdefault_int(CFG_S_GLOBAL,'splittitles',0) - self.COVER_SHOW=config.getdefault_int(CFG_S_GLOBAL,'cover_show',0) - self.NEW_PERIOD=config.getdefault_int(CFG_S_GLOBAL,'new_period',7) - zip_codepage=config.getdefault(CFG_S_GLOBAL,'zip_codepage','cp866') - self.BOOK_SHELF=config.getdefault_bool(CFG_S_GLOBAL,'book_shelf',True) - - self.EXT_LIST=self.FORMATS.lower().split() - - if zip_codepage.lower() in {'cp437','cp866','cp1251','utf-8'}: self.ZIP_CODEPAGE=zip_codepage.lower() - else: self.ZIP_CODEPAGE='cp437' - - CFG_S_SITE='site' - self.SITE_ID=config.get(CFG_S_SITE,'id') - self.SITE_TITLE=config.get(CFG_S_SITE,'title') - self.SITE_ICON=config.get(CFG_S_SITE,'icon') - self.SITE_AUTOR=config.get(CFG_S_SITE,'autor') - self.SITE_URL=config.get(CFG_S_SITE,'url') - self.SITE_EMAIL=config.get(CFG_S_SITE,'email') - self.SITE_MAINTITLE=config.get(CFG_S_SITE,'main_title') - - CFG_S_SCAND='scand' - self.SCAN_ON_START=config.getdefault_bool(CFG_S_SCAND,'scan_on_start',True) - self.PID_FILE=config.getdefault(CFG_S_SCAND,'pid_file',r'/tmp/sopds.pid') - self.SCAN_DAEMON=config.getdefault_bool(CFG_S_SCAND,'daemon',True) - self.DAY_OF_WEEK=config.getdefault_int(CFG_S_SCAND,'scan_day_of_week',0) - self.SCAN_INTERVAL=config.getdefault_int(CFG_S_SCAND,'scan_interval',0) - self.SCAN_TIME=config.getdefault(CFG_S_SCAND,'scan_time','00:00') - scand_logfile=config.getdefault(CFG_S_SCAND,'logfile','sopds-scand.log') - self.SCAND_LOGFILE=os.path.join(LOG_PATH,scand_logfile) - try: - (scan_hour,scan_min)=self.SCAN_TIME.split(':') - scan_hour=scan_hour.strip() - scan_min=scan_min.strip() - if scan_hour.isdigit(): - self.SCAN_HOUR=int(scan_hour) - else: - self.SCAN_HOUR=0 - if scan_min.isdigit(): - self.SCAN_MIN=int(scan_min) - else: - self.SCAN_MIN=0 - except: - (self.SCAN_HOUR,self.SCAN_MIN)=(0,0) - if self.SCAN_INTERVAL>0: - self.SCAN_TIMES=list(range(self.SCAN_HOUR*60+self.SCAN_MIN,1440,self.SCAN_INTERVAL)) - else: - self.SCAN_TIMES=[self.SCAN_HOUR*60+self.SCAN_MIN] - - CFG_S_HTTPD='httpd' - self.OPDS_PREFIX=config.getdefault(CFG_S_HTTPD,'opds_prefix',r'/opds') - self.WEB_PREFIX=config.getdefault(CFG_S_HTTPD,'web_prefix',r'/web') - self.HTTPD_PID_FILE=config.getdefault(CFG_S_HTTPD,'pid_file',r'/tmp/sopds-http.pid') - self.HTTP_DAEMON=config.getdefault_bool(CFG_S_HTTPD,'daemon',True) - self.PORT=config.getdefault_int(CFG_S_HTTPD,'port',8081) - self.BIND_ADDRESS=config.getdefault(CFG_S_HTTPD,'bind_address','0.0.0.0') - self.AUTH=config.getdefault_bool(CFG_S_HTTPD,'auth',False) - self.ACCOUNTS=config.getdefault(CFG_S_HTTPD,'accounts','') - httpd_logfile=config.getdefault(CFG_S_HTTPD,'logfile','sopds-httpd.log') - self.HTTPD_LOGFILE=os.path.join(LOG_PATH,httpd_logfile) - diff --git a/py/sopdscli.py b/py/sopdscli.py deleted file mode 100644 index 4e77e782a60a3d9c6bcfaecf388906f04f4a10fc..0000000000000000000000000000000000000000 --- a/py/sopdscli.py +++ /dev/null @@ -1,814 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import sys -import sopdscfg -import sopdsdb -import codecs -import os -import io -import time -import sopdsparse -import base64 -import subprocess -import zipf -import sopdswrap -import sopdstempl -from urllib import parse - -modeCGI = 0 -modeWSGI = 1 -modeINT = 2 - -####################################################################### -# -# Вспомогательные функции -# -def translit(s): - """Russian translit: converts 'привет'->'privet'""" - assert s is not str, "Error: argument MUST be string" - - table1 = str.maketrans("абвгдеёзийклмнопрстуфхъыьэАБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЬЭ", "abvgdeezijklmnoprstufh'y'eABVGDEEZIJKLMNOPRSTUFH'Y'E") - table2 = {'ж':'zh','ц':'ts','ч':'ch','ш':'sh','щ':'sch','ю':'ju','я':'ja', 'Ж':'Zh','Ц':'Ts','Ч':'Ch','Ш':'Sh','Щ':'Sch','Ю':'Ju','Я':'Ja', '«':'\'', '»':'\'','"':'\'','\n':' '} - for k in table2.keys(): - s = s.replace(k,table2[k]) - return s.translate(table1) - -def websym(s,attr=False): - """Replace special web-symbols""" - result = s - if attr: - table = {'"':'\''} - else: - table = {'&':'&','<':'<'} - for k in table.keys(): - result = result.replace(k,table[k]) - return result; - -####################################################################### -# -# Основной класс OPDS-клиента -# -class opdsClient(): - def __init__(self,cfg,mode=modeCGI): - self.cfg=cfg - if mode==modeWSGI: - self.moduleFile=self.cfg.WSGI_PATH - elif mode==modeINT: - self.moduleFile='' - else: - self.moduleFile=self.cfg.CGI_PATH - self.modulePath=self.moduleFile - self.opdsdb=sopdsdb.opdsDatabase(self.cfg.DB_NAME,self.cfg.DB_USER,self.cfg.DB_PASS,self.cfg.DB_HOST,self.cfg.ROOT_LIB) - self.site_data={'site_title':self.cfg.SITE_TITLE, 'site_subtitle':'Simple OPDS Catalog by www.sopds.ru. Version '+sopdscfg.VERSION,'modulepath':self.modulePath,'site_icon':self.cfg.SITE_ICON,'site_author':self.cfg.SITE_AUTOR,'site_url':self.cfg.SITE_URL,'site_email':self.cfg.SITE_EMAIL, 'charset':'utf-8'} - - self.template1=sopdstempl.opdsTemplate() - self.opdsWrapper=sopdswrap.baseWrapper(self.cfg, self.template1,self.site_data) - - self.template2=sopdstempl.webTemplate() - self.webWrapper=sopdswrap.baseWrapper(self.cfg, self.template2,self.site_data) - - self.Wrapper=self.opdsWrapper - - - def resetParams(self): - self.id_value='0' - self.type_value=0 - self.slice_value=0 - self.page_value=0 - self.ser_value=0 - self.alpha=0 - self.news=0 - self.np=0 - self.nl='' - self.searchTerm='' - self.user=None - self.method=0 - self.opdsWrapper.resetParams() - self.webWrapper.resetParams() - self.Wrapper=self.opdsWrapper - - def parseParams(self,environ): - self.environ=environ - qs = None - - if 'QUERY_STRING' in environ: - qs = parse.parse_qs(environ['QUERY_STRING']) - if 'REQUEST_URI' in environ: - URI=environ['REQUEST_URI'] - else: - URI=environ['PATH_INFO'] - - if self.cfg.WEB_PREFIX in URI: - self.Wrapper=self.webWrapper - self.modulePath=os.path.join(self.cfg.WEB_PREFIX,self.moduleFile) - if self.cfg.OPDS_PREFIX in URI: - self.Wrapper=self.opdsWrapper - self.modulePath=os.path.join(self.cfg.OPDS_PREFIX,self.moduleFile) - self.modulePath=os.path.normpath(self.modulePath) - - if 'id' in qs: - self.id_value=qs.get("id")[0] - else: - self.id_value="0" - if self.id_value.isdigit(): - if len(self.id_value)>1: - self.type_value = int(self.id_value[0:2]) - if len(self.id_value)>2: - self.slice_value = int(self.id_value[2:]) - - if 'page' in qs: - page=qs.get("page")[0] - if page.isdigit(): - self.page_value=int(page) - - if 'searchType' in qs: - searchType=qs.get("searchType")[0].strip() - if searchType=='books': self.type_value=71 - if searchType=='authors': self.type_value=72 - if searchType=='series': self.type_value=73 - - if 'searchTerm' in qs: - self.searchTerm=qs.get("searchTerm")[0].strip() - if self.type_value!=71 and self.type_value!=72 and self.type_value!=73: self.type_value=7 - self.slice_value=-1 - self.id_value='%02d&searchTerm=%s'%(self.type_value,self.searchTerm) - else: - self.searchTerm='' - - if 'alpha' in qs: - salpha=qs.get("alpha")[0].strip() - if salpha.isdigit(): self.alpha=int(salpha) - - if 'news' in qs: - self.news=1 - self.nl='&news=1' - self.np=self.cfg.NEW_PERIOD - - if 'ser' in qs: - ser=qs.get("ser")[0] - if ser.isdigit(): - self.ser_value=int(ser) - - def setUser(self,user): - self.user=user - - def add_response_body(self, string='', encoding='utf8'): - self.Wrapper.add_response_body(string,encoding) - - def add_response_binary(self, data): - self.Wrapper.add_response_binary(data) - - def add_response_header(self,list): - self.Wrapper.add_response_header(list) - - def set_response_status(self,status): - self.Wrapper.set_response_status(status) - - def write_response_headers(self, encoding='utf8'): - self.Wrapper.write_response_headers(encoding) - - def write_response(self): - self.Wrapper.write_response() - - def get_response_status(self): - return self.Wrapper.response_status - - def get_response_headers(self): - return self.Wrapper.response_headers - - def get_response_body(self): - return self.Wrapper.response_body - - def header(self, page_data): - self.Wrapper.document_header(page_data) - self.Wrapper.page_top(page_data) - self.Wrapper.page_title(page_data) - - def footer(self,page_data={}): -# Debug output commented -# for key in self.environ.keys(): -# self.add_response_body("{0}:{1}".format(key,self.environ[key], end=" ")) - self.Wrapper.page_bottom(page_data) - self.Wrapper.document_footer(page_data) - - def main_menu(self): - dbinfo=self.opdsdb.getdbinfo(self.cfg.DUBLICATES_SHOW,self.cfg.BOOK_SHELF,self.user) - self.Wrapper.main_menu(self.user,dbinfo) - - def new_menu(self): - newinfo=self.opdsdb.getnewinfo(self.cfg.DUBLICATES_SHOW,self.cfg.NEW_PERIOD) - self.Wrapper.new_menu(newinfo) - - def authors_submenu(self,author_id): - self.Wrapper.authors_submenu(author_id) - - def opensearch_links(self,page_data): - self.Wrapper.opensearch_links(page_data) - - def opensearch_forms(self,page_data): - self.Wrapper.opensearch_forms(page_data) - - def get_authors(self,book_id): - return self.Wrapper.get_authors(self.opdsdb.getauthors(book_id)) - - def get_genres(self,book_id): - return self.Wrapper.get_genres(self.opdsdb.getgenres(book_id)) - - def get_series(self,book_id): - return self.Wrapper.get_series(self.opdsdb.getseries(book_id)) - - def entry_acquisition(self,acq_data): - self.Wrapper.entry_acquisition(acq_data) - - def entry_navigation(self,nav_data): - self.Wrapper.entry_navigation(nav_data) - - def page_control(self, page_data): - data=page_data.copy() - data['link_id']=self.id_value - data['page']=self.page_value - if self.page_value>0: - data['page_prev']=self.page_value-1 - else: - data['page_prev']=-1 - if self.opdsdb.next_page: - data['page_next']=self.page_value+1 - else: - data['page_next']=-1; - self.Wrapper.page_control(data) - - def alphabet_menu(self,iid_value): - self.Wrapper.alphabet_menu(iid_value,self.nl) - - def response_search(self): - self.Wrapper.opensearch() - - def response_main(self): - page_data={'page_id':'id:main', 'page_title':self.cfg.SITE_TITLE, 'page_updated':time.strftime("%Y-%m-%d %H:%M:%S")} - self.header(page_data) - self.main_menu() - self.footer(page_data) - - def response_catalogs(self): - """ Выбрана сортировка 'По каталогам' """ - page_data={'page_id':'id:catalogs', 'page_title':'Сортировка по каталогам хранения', 'page_updated':time.strftime("%Y-%m-%d %H:%M:%S")} - self.header(page_data) - for (item_type,item_id,item_name,item_path,reg_date,item_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getitemsincat(self.slice_value,self.cfg.MAXITEMS,self.page_value): - if item_type==1: - id='01'+str(item_id) - nav_data={'link_id':id,'item_id':item_id,'e_date':reg_date,'e_title':websym(item_title),'e_id':'item:%s'%(item_id),'e_nav_info':'', - 'nl':self.nl} - self.entry_navigation(nav_data) - if item_type==2: - id='90'+str(item_id) - (authors, authors_link) = self.get_authors(item_id) - (genres, genres_link) = self.get_genres(item_id) - (series, series_link) = self.get_series(item_id) - acq_data={'link_id':id,'item_id':item_id,'filename':item_name,'e_date':reg_date,'e_title':websym(item_title),'e_id':'item:%s'%(item_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl, 'dcount':0} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer() - - def response_alpha(self): - """ Вывод дополнительного меню алфавита для сортировок по Наименованиям, по Авторам и по Жанрам """ - page_data={'page_id':'id:alphabet', 'page_title':'SOPDS|Выбор языка', 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - self.alphabet_menu(self.id_value[2:]) - self.footer(page_data) - - def response_authors(self): - """ Cортировка 'По авторам' - выбор по нескольким первым буквам автора """ - i=self.slice_value - letter="" - while i>0: - letter=chr(i%10000)+letter - i=i//10000 - page_data={'page_id':'id:preauthors:%s'%letter,'page_title':'Выбор авторов "%s"'%letter, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (letters,cnt) in self.opdsdb.getauthor_2letters(letter,self.alpha,self.np): - id="" - for i in range(len(letters)): - id+='%04d'%(ord(letters[i])) - - if self.cfg.SPLITTITLES==0 or cnt<=self.cfg.SPLITTITLES or len(letters)>10: - id='12'+id - else: - id='02'+id - - nav_data={'link_id':id,'e_date':None,'e_title':letters,'e_id':id,'e_nav_info':('Всего: '+str(cnt)+' автора(ов).'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.footer(page_data) - - def response_series(self): - """ Cортировка 'По сериям' - выбор по нескольким первым буквам серии """ - i=self.slice_value - letter="" - while i>0: - letter=chr(i%10000)+letter - i=i//10000 - page_data={'page_id':'id:preseries:%s'%letter,'page_title':'Выбор серий "%s"'%letter, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (letters,cnt) in self.opdsdb.getseries_2letters(letter,self.alpha,self.np): - id="" - for i in range(len(letters)): - id+='%04d'%(ord(letters[i])) - - if self.cfg.SPLITTITLES==0 or cnt<=self.cfg.SPLITTITLES or len(letters)>10: - id='16'+id - else: - id='06'+id - - nav_data={'link_id':id,'e_date':None,'e_title':letters,'e_id':id,'e_nav_info':('Всего: '+str(cnt)+' серий.'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.footer(page_data) - - def response_titles(self): - """ Cортировка 'По наименованию' - выбор по нескольким первым буквам наименования """ - i=self.slice_value - letter="" - while i>0: - letter=chr(i%10000)+letter - i=i//10000 - page_data={'page_id':'id:pretitle:%s'%letter,'page_title':'Выбор наименований "%s"'%letter, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (letters,cnt) in self.opdsdb.gettitle_2letters(letter,self.cfg.DUBLICATES_SHOW,self.alpha,self.np): - id="" - for i in range(len(letters)): - id+='%04d'%(ord(letters[i])) - - if self.cfg.SPLITTITLES==0 or cnt<=self.cfg.SPLITTITLES or len(letters)>10: - id='13'+id - else: - id='03'+id - - nav_data={'link_id':id,'e_date':None,'e_title':letters,'e_id':id,'e_nav_info':('Всего: '+str(cnt)+' наименований.'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.footer(page_data) - - def response_titles_search(self): - """ Выдача списка книг по наименованию или на основании поискового запроса """ - if self.slice_value>=0: - i=self.slice_value - letter="" - while i>0: - letter=chr(i%10000)+letter - i=i//10000 - else: - letter="%"+self.searchTerm - page_data={'page_id':'id:title:%s'%letter,'page_title':'Книги по наименованию "%s"'%letter, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (book_id,book_name,book_path,reg_date,book_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getbooksfortitle(letter,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW,self.np): - id='90'+str(book_id) - (authors, authors_link) = self.get_authors(book_id) - (genres, genres_link) = self.get_genres(book_id) - (series, series_link) = self.get_series(book_id) - acq_data={'link_id':id,'item_id':book_id,'filename':book_name,'e_date':reg_date,'e_title':websym(book_title),'e_id':'item:%s'%(book_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl, 'dcount':self.opdsdb.getdoublecount(book_id)} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer(page_data) - - def response_doubles(self): - """ Вывод дубликатов для выбранной книги """ - page_data={'page_id':'id:doubles:%s'%self.slice_value,'page_title':'Дубликаты для книги id=%s'%self.slice_value, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (book_id,book_name,book_path,reg_date,book_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getdoubles(self.slice_value,self.cfg.MAXITEMS,self.page_value): - id='90'+str(book_id) - (authors, authors_link) = self.get_authors(book_id) - (genres, genres_link) = self.get_genres(book_id) - (series, series_link) = self.get_series(book_id) - acq_data={'link_id':id,'item_id':book_id,'filename':book_name,'e_date':reg_date,'e_title':websym(book_title),'e_id':'item:%s'%(book_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl,'dcount':self.opdsdb.getdoublecount(book_id)} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer(page_data) - - - def response_genres_sections(self): - """ Cортировка 'По жанрам' - показ секций """ - page_data={'page_id':'id:genre:sections','page_title':'Список жанров', 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (genre_id,genre_section,cnt) in self.opdsdb.getgenres_sections(self.cfg.DUBLICATES_SHOW,self.np): - id='14'+str(genre_id) - nav_data={'link_id':id,'e_date':None,'e_title':genre_section,'e_id':'genre:%s'%(genre_id),'e_nav_info':('Всего: '+str(cnt)+' книг.'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.footer(page_data) - - def response_genres_subsections(self): - """ Cортировка 'По жанрам' - показ подсекций """ - page_data={'page_id':'id:genre:subsections:%s'%self.slice_value,'page_title':'Список жанров (уровень 2)', 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (genre_id,genre_subsection,cnt) in self.opdsdb.getgenres_subsections(self.slice_value,self.cfg.DUBLICATES_SHOW,self.np): - id='24'+str(genre_id) - if self.cfg.ALPHA: id='30'+id - nav_data={'link_id':id,'e_date':None,'e_title':genre_subsection,'e_id':'genre:%s'%(genre_id),'e_nav_info':('Всего: '+str(cnt)+' книг.'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.footer(page_data) - - def response_genres_books(self): - """ Выдача списка книг по жанру """ - page_data={'page_id':'id:genres:%s'%self.slice_value,'page_title':'Список книг по выбранному жанру', 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (book_id,book_name,book_path,reg_date,book_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getbooksforgenre(self.slice_value,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW,self.alpha,self.np): - id='90'+str(book_id) - (authors, authors_link) = self.get_authors(book_id) - (genres, genres_link) = self.get_genres(book_id) - (series, series_link) = self.get_series(book_id) - acq_data={'link_id':id,'item_id':book_id,'filename':book_name,'e_date':reg_date,'e_title':websym(book_title),'e_id':'item:%s'%(book_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl, 'dcount':self.opdsdb.getdoublecount(book_id)} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer(page_data) - - def response_last(self): - """ Cортировка 'Последние поступления' """ - page_data={'page_id':'id:news','page_title':'Последние поступления за %s дней'%self.cfg.NEW_PERIOD, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - self.new_menu() - self.footer(page_data) - - def response_search_type(self): - page_data={'page_id':'id:search:%s'%self.searchTerm,'page_title':'Поиск %s'%self.searchTerm, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ"),'searchterm':parse.quote(self.searchTerm)} - self.header(page_data) - self.opensearch_forms(page_data) - self.footer(page_data) - - def response_bookshelf(self): - """ Выдача списка книг на книжной полке """ - page_data={'page_id':'id:bookshelf:%s'%self.user,'page_title':'Книги пользователя %s'%self.user, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (book_id,book_name,book_path,reg_date,book_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getbooksforuser(self.user,self.cfg.MAXITEMS,self.page_value): - id='90'+str(book_id) - (authors, authors_link) = self.get_authors(book_id) - (genres, genres_link) = self.get_genres(book_id) - (series, series_link) = self.get_series(book_id) - acq_data={'link_id':id,'item_id':book_id,'filename':book_name,'e_date':reg_date,'e_title':websym(book_title),'e_id':'item:%s'%(book_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl, 'dcount':self.opdsdb.getdoublecount(book_id)} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer(page_data) - - def response_authors_search(self): - """ Выдача списка авторов по имени или на основании поиска """ - if self.slice_value>0: - i=self.slice_value - letter="" - while i>0: - letter=chr(i%10000)+letter - i=i//10000 - else: - letter="%"+self.searchTerm - - page_data={'page_id':'id:authors:%s'%letter,'page_title':'Авторы по имени "%s"'%letter, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (author_id,first_name, last_name,cnt) in self.opdsdb.getauthorsbyl(letter,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW,self.np): - id='22'+str(author_id) - nav_data={'link_id':id,'e_date':None,'e_title':(last_name+' '+first_name),'e_id':'author:%s'%(author_id),'e_nav_info':('Всего: '+str(cnt)+' книг.'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.page_control(page_data) - self.footer(page_data) - - def response_series_search(self): - """ Выдача списка серий по названию или на основании поиска """ - if self.slice_value>0: - i=self.slice_value - letter="" - while i>0: - letter=chr(i%10000)+letter - i=i//10000 - else: - letter="%"+self.searchTerm - - page_data={'page_id':'id:series:%s'%letter,'page_title':'Список серий книг "%s"'%letter, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (ser_id,ser,cnt) in self.opdsdb.getseriesbyl(letter,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW,self.np): - id='26'+str(ser_id) - nav_data={'link_id':id,'e_date':None,'e_title':ser,'e_id':'series:%s'%(ser_id),'e_nav_info':('Всего: '+str(cnt)+' книг.'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.page_control(page_data) - self.footer(page_data) - - def response_authors_submenu(self): - """ Выдача подменю вывода книг по автору - в случае флага новинок будет сразу переход к выдаче книг автора """ - (first_name,last_name)=self.opdsdb.getauthor_name(self.slice_value) - page_data={'page_id':'id:autor:%s %s'%(last_name,first_name),'page_title':'Книги автора %s %s'%(last_name,first_name), 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - self.authors_submenu(self.slice_value) - self.footer(page_data) - - def response_authors_series(self): - """ Выдача серий по автору """ - (first_name,last_name)=self.opdsdb.getauthor_name(self.slice_value) - page_data={'page_id':'id:autorseries:%s %s'%(last_name,first_name),'page_title':'Серии книг автора %s %s'%(last_name,first_name), 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (ser_id,ser,cnt) in self.opdsdb.getseriesforauthor(self.slice_value,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW): - id='34'+str(self.slice_value)+'&ser='+str(ser_id) - nav_data={'link_id':id,'e_date':None,'e_title':ser,'e_id':'series:%s'%(ser_id),'e_nav_info':('Всего: '+str(cnt)+' книг.'), - 'nl':self.nl} - self.entry_navigation(nav_data) - self.page_control(page_data) - self.footer(page_data) - - def response_authors_alpha(self): - """ Выдача списка книг по автору по алфавиту """ - (first_name,last_name)=self.opdsdb.getauthor_name(self.slice_value) - page_data={'page_id':'id:autorbooks:%s %s'%(last_name,first_name),'page_title':'Книги автора %s %s'%(last_name,first_name), 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (book_id,book_name,book_path,reg_date,book_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getbooksforautor(self.slice_value,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW,self.np): - id='90'+str(book_id) - (authors, authors_link) = self.get_authors(book_id) - (genres, genres_link) = self.get_genres(book_id) - (series, series_link) = self.get_series(book_id) - acq_data={'link_id':id,'item_id':book_id,'filename':book_name,'e_date':reg_date,'e_title':websym(book_title),'e_id':'item:%s'%(book_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl, 'dcount':self.opdsdb.getdoublecount(book_id)} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer(page_data) - - def response_authors_series_books(self): - """ Выдача списка книг по автору по выбранной серии (или вне серий если ser_value==0) """ - (first_name,last_name)=self.opdsdb.getauthor_name(self.slice_value) - page_data={'page_id':'id:autorbooks:%s %s'%(last_name,first_name),'page_title':'Книги автора %s %s'%(last_name,first_name), 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (book_id,book_name,book_path,reg_date,book_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getbooksforautorser(self.slice_value,self.ser_value,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW): - id='90'+str(book_id) - (authors, authors_link) = self.get_authors(book_id) - (genres, genres_link) = self.get_genres(book_id) - (series, series_link) = self.get_series(book_id) - acq_data={'link_id':id,'item_id':book_id,'filename':book_name,'e_date':reg_date,'e_title':websym(book_title),'e_id':'item:%s'%(book_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl, 'dcount':self.opdsdb.getdoublecount(book_id)} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer(page_data) - - def response_series_books(self): - """ Выдача списка книг по серии """ - (ser_name,)=self.opdsdb.getser_name(self.slice_value) - page_data={'page_id':'id:ser:%s'%ser_name,'page_title':'Книги серии %s'%ser_name, 'page_updated':time.strftime("%Y-%m-%dT%H:%M:%SZ")} - self.header(page_data) - for (book_id,book_name,book_path,reg_date,book_title,annotation,docdate,format,fsize,cover,cover_type) in self.opdsdb.getbooksforser(self.slice_value,self.cfg.MAXITEMS,self.page_value,self.cfg.DUBLICATES_SHOW,self.np): - id='90'+str(book_id) - (authors, authors_link) = self.get_authors(book_id) - (genres, genres_link) = self.get_genres(book_id) - (series, series_link) = self.get_series(book_id) - acq_data={'link_id':id,'item_id':book_id,'filename':book_name,'e_date':reg_date,'e_title':websym(book_title),'e_id':'item:%s'%(book_id), - 'annotation':websym(annotation), 'docdate':docdate, 'format':format,'cover':cover,'cover_type':cover_type,'filesize':fsize//1024, - 'authors':authors,'genres':genres,'series':series,'authors_link':authors_link,'genres_link':genres_link, 'series_link':series_link, - 'nl':self.nl, 'dcount':self.opdsdb.getdoublecount(book_id)} - self.entry_acquisition(acq_data) - self.page_control(page_data) - self.footer(page_data) - - def response_book_file(self): - """ Выдача файла книги """ - (book_name,book_path,reg_date,format,title,annotation,docdate,cat_type,cover,cover_type,fsize)=self.opdsdb.getbook(self.slice_value) - if self.cfg.BOOK_SHELF and self.user!=None: self.opdsdb.addbookshelf(self.user,self.slice_value) - full_path=os.path.join(self.cfg.ROOT_LIB,book_path) - if self.cfg.TITLE_AS_FN: transname=translit(title+'.'+format) - else: transname=translit(book_name) - if format=="fb2": content_type='text/xml' - elif format=="epub": content_type='application/epub+zip' - elif format=="mobi": content_type='application/x-mobipocket-ebook' - else: content_type='application/octet-stream' - # HTTP Header - self.add_response_header([('Content-Type',content_type+'; name="'+transname+'"')]) - self.add_response_header([('Content-Disposition','attachment; filename="'+transname+'"')]) - self.add_response_header([('Content-Transfer-Encoding','binary')]) - if cat_type==sopdsdb.CAT_NORMAL: - file_path=os.path.join(full_path,book_name) - book_size=os.path.getsize(file_path.encode('utf-8')) - self.add_response_header([('Content-Length',str(book_size))]) - fo=codecs.open(file_path.encode("utf-8"), "rb") - s=fo.read() - self.add_response_binary(s) - fo.close() - elif cat_type==sopdsdb.CAT_ZIP: - fz=codecs.open(full_path.encode("utf-8"), "rb") - z = zipf.ZipFile(fz, 'r', allowZip64=True) - book_size=z.getinfo(book_name).file_size - self.add_response_header([('Content-Length',str(book_size))]) - fo= z.open(book_name) - s=fo.read() - self.add_response_binary(s) - fo.close() - z.close() - fz.close() - - def response_book_zip(self): - """ Выдача файла книги в ZIP формате """ - (book_name,book_path,reg_date,format,title,annotation,docdate,cat_type,cover,cover_type,fsize)=self.opdsdb.getbook(self.slice_value) - if self.cfg.BOOK_SHELF and self.user!=None: self.opdsdb.addbookshelf(self.user,self.slice_value) - full_path=os.path.join(self.cfg.ROOT_LIB,book_path) - if self.cfg.TITLE_AS_FN: transname=translit(title+'.'+format) - else: transname=translit(book_name) - # HTTP Header - self.add_response_header([('Content-Type','application/zip; name="'+transname+'"')]) - self.add_response_header([('Content-Disposition','attachment; filename="'+transname+'.zip"')]) - self.add_response_header([('Content-Transfer-Encoding','binary')]) - if cat_type==sopdsdb.CAT_NORMAL: - file_path=os.path.join(full_path,book_name) - dio = io.BytesIO() - z = zipf.ZipFile(dio, 'w', zipf.ZIP_DEFLATED) - z.write(file_path.encode('utf-8'),transname) - z.close() - buf = dio.getvalue() - self.add_response_header([('Content-Length',str(len(buf)))]) - self.add_response_binary(buf) - elif cat_type==sopdsdb.CAT_ZIP: - fz=codecs.open(full_path.encode("utf-8"), "rb") - zi = zipf.ZipFile(fz, 'r', allowZip64=True) - fo= zi.open(book_name) - s=fo.read() - fo.close() - zi.close() - fz.close() - - dio = io.BytesIO() - zo = zipf.ZipFile(dio, 'w', zipf.ZIP_DEFLATED) - zo.writestr(transname,s) - zo.close() - - buf = dio.getvalue() - self.add_response_header([('Content-Length',str(len(buf)))]) - self.add_response_binary(buf) - - def response_book_convert(self): - """ Выдача файла книги после конвертации в EPUB или mobi """ - (book_name,book_path,reg_date,format,title,annotation,docdate,cat_type,cover,cover_type,fsize)=self.opdsdb.getbook(self.slice_value) - if self.cfg.BOOK_SHELF and self.user!=None: self.opdsdb.addbookshelf(self.user, self.slice_value) - full_path=os.path.join(self.cfg.ROOT_LIB,book_path) - (n,e)=os.path.splitext(book_name) - if self.type_value==93: - convert_type='.epub' - converter_path=self.cfg.FB2TOEPUB_PATH - content_type='application/epub+zip' - elif self.type_value==94: - convert_type='.mobi' - converter_path=self.cfg.FB2TOMOBI_PATH - content_type='application/x-mobipocket-ebook' - else: - content_type='application/octet-stream' - if self.cfg.TITLE_AS_FN: transname=translit(title)+convert_type - else: transname=translit(n)+convert_type - if cat_type==sopdsdb.CAT_NORMAL: - tmp_fb2_path=None - file_path=os.path.join(full_path,book_name) - elif cat_type==sopdsdb.CAT_ZIP: - fz=codecs.open(full_path.encode("utf-8"), "rb") - z = zipf.ZipFile(fz, 'r', allowZip64=True) - z.extract(book_name,self.cfg.TEMP_DIR) - tmp_fb2_path=os.path.join(self.cfg.TEMP_DIR,book_name) - file_path=tmp_fb2_path - - tmp_conv_path=os.path.join(self.cfg.TEMP_DIR,transname) - proc = subprocess.Popen(("%s %s %s"%(converter_path,("\"%s\""%file_path),"\"%s\""%tmp_conv_path)).encode('utf8'), shell=True, stdout=subprocess.PIPE) - out = proc.stdout.readlines() - - if os.path.isfile(tmp_conv_path): - fo=codecs.open(tmp_conv_path, "rb") - s=fo.read() - # HTTP Header - self.add_response_header([('Content-Type',content_type+'; name="'+transname+'"')]) - self.add_response_header([('Content-Disposition','attachment; filename="'+transname+'"')]) - self.add_response_header([('Content-Transfer-Encoding','binary')]) - self.add_response_header([('Content-Length',str(len(s)))]) - self.add_response_binary(s) - fo.close() - else: - self.set_response_status('404 Not Found') - - try: os.remove(tmp_fb2_path.encode('utf-8')) - except: pass - try: os.remove(tmp_conv_path) - except: pass - - def response_book_cover(self): - """ Выдача Обложки На лету """ - (book_name,book_path,reg_date,format,title,annotation,docdate,cat_type,cover,cover_type,fsize)=self.opdsdb.getbook(self.slice_value) - c0=0 - if format=='fb2': - full_path=os.path.join(self.cfg.ROOT_LIB,book_path) - fb2=sopdsparse.fb2parser(1) - if cat_type==sopdsdb.CAT_NORMAL: - file_path=os.path.join(full_path,book_name) - fo=codecs.open(file_path.encode("utf-8"), "rb") - fb2.parse(fo,0) - fo.close() - elif cat_type==sopdsdb.CAT_ZIP: - fz=codecs.open(full_path.encode("utf-8"), "rb") - z = zipf.ZipFile(fz, 'r', allowZip64=True) - fo = z.open(book_name) - fb2.parse(fo,0) - fo.close() - z.close() - fz.close() - - if len(fb2.cover_image.cover_data)>0: - try: - s=fb2.cover_image.cover_data - dstr=base64.b64decode(s) - ictype=fb2.cover_image.getattr('content-type') - self.add_response_header([('Content-Type',ictype)]) - self.add_response_binary(dstr) - c0=1 - except: - c0=0 - - if c0==0: - if os.path.exists(sopdscfg.NOCOVER_PATH): - self.add_response_header([('Content-Type','image/jpeg')]) - f=open(sopdscfg.NOCOVER_PATH,"rb") - self.add_response_binary(f.read()) - f.close() - else: - self.set_response_status('404 Not Found') - - def make_response(self): - self.opdsdb.openDB() - if self.opdsdb.errcode==0 or self.opdsdb.errcode==4: - if self.type_value==0: - self.response_main() - elif self.type_value==1: - self.response_catalogs() - - elif self.type_value==2: - self.response_authors() - elif self.type_value==12 or self.type_value==72: - self.response_authors_search() - elif self.type_value==22 and self.np==0: - self.response_authors_submenu() - elif self.type_value==31: - self.response_authors_series() - elif self.type_value==33 or (self.type_value==22 and self.np!=0): - self.response_authors_alpha() - elif self.type_value==34: - self.response_authors_series_books() - - elif self.type_value==3: - self.response_titles() - elif self.type_value==13 or self.type_value==71: - self.response_titles_search() - elif self.type_value==23: - self.response_doubles() - - elif self.type_value==4: - self.response_genres_sections() - elif self.type_value==14: - self.response_genres_subsections() - elif self.type_value==24: - self.response_genres_books() - - elif self.type_value==5: - self.response_last() - - elif self.type_value==6: - self.response_series() - elif self.type_value==16 or self.type_value==73: - self.response_series_search() - elif self.type_value==26: - self.response_series_books() - - elif self.type_value==7: - self.response_search_type() - elif self.type_value==8: - self.response_bookshelf() - elif self.type_value==30: - self.response_alpha() - - elif self.type_value==9: - self.response_search() - - elif self.type_value==91: - self.response_book_file() - elif self.type_value==92: - self.response_book_zip() - elif self.type_value==93 or self.type_value==94: - self.response_book_convert() - elif self.type_value==99: - self.response_book_cover() - - self.opdsdb.closeDB() - diff --git a/py/sopdsd.py b/py/sopdsd.py deleted file mode 100755 index 7dd8f5ea21e78a37473d7fbedac31fe577d48816..0000000000000000000000000000000000000000 --- a/py/sopdsd.py +++ /dev/null @@ -1,353 +0,0 @@ -#!/usr/bin/env python3 - -import logging -import sys, os, time, atexit -from signal import SIGTERM -from multiprocessing import Process - -import sopdscfg -import sopdserve -from sopdscan import opdsScanner - -typeSCAND = 0 -typeHTTPD = 1 - -class Daemon(object): - """ - Subclass Daemon class and override the run() method. - """ - def __init__(self, scan_pidfile, http_pidfile, stdin='/dev/null', scan_stdout='/dev/null', http_stdout='/dev/null', scan_stderr='/dev/null', http_stderr='/dev/null', enable_scand=True, enable_httpd=True): - self.stdin = stdin - self.scan_stdout = scan_stdout - self.scan_stderr = scan_stderr - self.http_stdout = http_stdout - self.http_stderr = http_stderr - self.scan_pidfile = scan_pidfile - self.http_pidfile = http_pidfile - self.enable_httpd = enable_httpd - self.enable_scand = enable_scand - self.daemon_type = 0 - - def daemonize(self): - """ - Deamonize, do double-fork magic. - """ - try: - pid = os.fork() - if pid > 0: - # Exit first parent. - sys.exit(0) - except OSError as e: - message = "Fork #1 failed: {}\n".format(e) - sys.stderr.write(message) - sys.exit(1) - - # Decouple from parent environment. - os.chdir("/") - os.setsid() - os.umask(0) - - # Do second fork (SCAN DAEMON) - if self.enable_scand: - try: - pid = os.fork() - if pid > 0: - # Exit from second parent. - sys.exit(0) - except OSError as e: - message = "Fork #2 (scand) failed: {}\n".format(e) - sys.stderr.write(message) - sys.exit(1) - - # Do third fork (HTTPD DAEMON) - if self.enable_httpd: - try: - pid = os.fork() - if pid>0 and not self.enable_scand: - # Exit from second parent. - sys.exit(0) - except OSError as e: - message = "Fork #3 (httpd) failed: {}. Exitting\n".format(e) - sys.stderr.write(message) - sys.exit(1) - - - if (pid>0 and self.enable_httpd) or (self.enable_httpd and not self.enable_scand): - print('SOPDS HTTP Daemon going to background, PID: {}'.format(os.getpid(),end="\r")) - self.daemon_type=typeHTTPD - self.pidfile=self.http_pidfile - self.stdout=self.http_stdout - self.stderr=self.http_stderr - else: - print('SOPDS SCAN Daemon going to background, PID: {}'.format(os.getpid(),end="\r")) - self.daemon_type=typeSCAND - self.pidfile=self.scan_pidfile - self.stdout=self.scan_stdout - self.stderr=self.scan_stderr - - # Redirect standard file descriptors. - sys.stdout.flush() - sys.stderr.flush() - si = open(self.stdin, 'r') - so = open(self.stdout, 'a+') - se = open(self.stderr, 'a+') - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) - - # Write pidfile. - pid = str(os.getpid()) - open(self.pidfile,'w+').write("{}\n".format(pid)) - - # Register a function to clean up. - atexit.register(self.delpid) - - def delpid(self): - os.remove(self.pidfile) - - def start(self): - """ - Start daemon. - """ - # Check pidfile to see if the daemon already runs. - scan_pid=None - http_pid=None - - if self.enable_scand: - try: - pf = open(self.scan_pidfile,'r') - scan_pid = int(pf.read().strip()) - pf.close() - except IOError: - scan_pid = None - - if scan_pid: - message = "Pidfile {} for SOPDS SCAN daemon already exist. Daemon already running?\n".format(self.scan_pidfile) - sys.stderr.write(message) - - - if self.enable_httpd: - try: - pf = open(self.http_pidfile,'r') - http_pid = int(pf.read().strip()) - pf.close() - except IOError: - http_pid = None - - if http_pid: - message = "Pidfile {} for SOPDS HTTP daemon already exist. Daemon already running?\n".format(self.http_pidfile) - sys.stderr.write(message) - - if (scan_pid and self.enable_scand) or (http_pid and self.enable_httpd): - sys.exit(1) - - # Start daemon. - self.daemonize() - self.run() - - def status(self): - """ - Get status of daemon. - """ - scan_pid = None - http_pid = None - - if self.enable_scand: - try: - pf = open(self.scan_pidfile,'r') - scan_pid = int(pf.read().strip()) - pf.close() - except IOError: - message = "There is not PID file {}. SOPDS SCAN Daemon already running?\n".format(self.scan_pidfile) - sys.stderr.write(message) - scan_pid = None - - if self.enable_httpd: - try: - pf = open(self.http_pidfile,'r') - http_pid = int(pf.read().strip()) - pf.close() - except IOError: - message = "There is not PID file {}. SOPDS HTTP Daemon already running?\n".format(self.http_pidfile) - sys.stderr.write(message) - http_pid=None - - if not ((scan_pid or not self.enable_scand) and (http_pid or not self.enable_httpd)): - sys.exit(1) - - if self.enable_scand: - try: - procfile = open("/proc/{}/status".format(scan_pid), 'r') - procfile.close() - message = "There is a SOPDS SCAN process with the PID {}\n".format(scan_pid) - sys.stdout.write(message) - except IOError: - message = "There is not a SOPDS SCAN process with the PID {}\n".format(self.scan_pid) - sys.stdout.write(message) - - if self.enable_httpd: - try: - procfile = open("/proc/{}/status".format(http_pid), 'r') - procfile.close() - message = "There is a SOPDS HTTP process with the PID {}\n".format(http_pid) - sys.stdout.write(message) - except IOError: - message = "There is not a SOPDS HTTP process with the PID {}\n".format(self.http_pid) - sys.stdout.write(message) - - - def stop(self): - """ - Stop the daemon. - """ - # Get the pid from pidfile. - scan_pid=None - http_pid=None - - if self.enable_scand: - try: - pf = open(self.scan_pidfile,'r') - scan_pid = int(pf.read().strip()) - pf.close() - except IOError as e: - message = str(e) + "\n SOPDS SCAN Daemon not running?\n" - sys.stderr.write(message) - scan_pid = None - - if scan_pid: - try: - os.kill(scan_pid, SIGTERM) - time.sleep(1) - except OSError as e: - print(str(e)) - - try: - if os.path.exists(self.scan_pidfile): - os.remove(self.scan_pidfile) - except IOError as e: - message = str(e) + "\nCan not remove pid file {}".format(self.scan_pidfile) - sys.stderr.write(message) - - if self.enable_httpd: - try: - pf = open(self.http_pidfile,'r') - http_pid = int(pf.read().strip()) - pf.close() - except IOError as e: - message = str(e) + "\n SOPDS HTTP Daemon not running?\n" - sys.stderr.write(message) - http_pid = None - - if http_pid: - try: - os.kill(http_pid, SIGTERM) - time.sleep(1) - except OSError as e: - print(str(e)) - - try: - if os.path.exists(self.http_pidfile): - os.remove(self.http_pidfile) - except IOError as e: - message = str(e) + "\nCan not remove pid file {}".format(self.scan_pidfile) - sys.stderr.write(message) - - def restart(self): - """ - Restart daemon. - """ - self.stop() - time.sleep(1) - self.start() - - def run(self): - """ - You should override this method when you subclass Daemon. - It will be called after the process has been daemonized by start() or restart(). - """ - -class opdsDaemon(Daemon): - def __init__(self): - self.start_scan=False - self.cfg=sopdscfg.cfgreader() - if not (self.cfg.SCAN_DAEMON or self.cfg.HTTP_DAEMON): - print('Check configuration file. No daemons enabled.') - sys.exit(0) - - self.logger = logging.getLogger('') - self.logger.setLevel(self.cfg.LOGLEVEL) - formatter=logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') - self.fh = logging.FileHandler(self.cfg.SCAND_LOGFILE) - self.fh.setLevel(self.cfg.LOGLEVEL) - self.fh.setFormatter(formatter) - self.logger.addHandler(self.fh) - self.logger.info('sopdsDaemon __init__()...') - - self.scanner=opdsScanner(self.cfg, self.logger) - - Daemon.__init__(self, self.cfg.PID_FILE, self.cfg.HTTPD_PID_FILE, '/dev/null', self.cfg.SCAND_LOGFILE,self.cfg.HTTPD_LOGFILE,self.cfg.SCAND_LOGFILE,self.cfg.HTTPD_LOGFILE, self.cfg.SCAN_DAEMON, self.cfg.HTTP_DAEMON) - - def start(self): - self.logger.info('sopdsDaemon start()...') - Daemon.start(self) - - def delpid(self): - self.logger.info('sopdsDaemon delpid()...') - Daemon.delpid(self) - - def status(self): - self.logger.info('sopdsDaemon status()...') - Daemon.status(self) - - def stop(self): - self.logger.info('sopdsDaemon stop()...') - Daemon.stop(self) - - def restart(self): - self.logger.info('sopdsDaemon restart()...') - Daemon.restart(self) - - def run_scanner(self): - self.cfg.parse() - self.fh.setLevel(self.cfg.LOGLEVEL) - self.logger.info('sopdsDaemon entering in main loop...') - - while True: - t=time.localtime() - if (((self.cfg.DAY_OF_WEEK==0) or (self.cfg.DAY_OF_WEEK==t.tm_wday+1)) and (t.tm_hour*60+t.tm_min in self.cfg.SCAN_TIMES)) or (self.cfg.SCAN_ON_START and not self.start_scan): - self.scanner.scan_all() - self.start_scan=True - time.sleep(30) - - def run_server(self): - sopdserve.start_server(self.cfg) - - def run(self): - if self.daemon_type == typeSCAND: - self.run_scanner() - else: - self.run_server() - -if __name__ == "__main__": - - daemon = opdsDaemon() - if len(sys.argv) == 2: -# print('{} {}'.format(sys.argv[0],sys.argv[1])) - - if 'start' == sys.argv[1]: - daemon.start() - elif 'stop' == sys.argv[1]: - daemon.stop() - elif 'restart' == sys.argv[1]: - daemon.restart() - elif 'status' == sys.argv[1]: - daemon.status() - else: - print ("Unknown command") - sys.exit(2) - sys.exit(0) - else: - print ('show cmd deamon usage') - print ("Usage: {} start|stop|restart|status".format(sys.argv[0])) - sys.exit(2) - diff --git a/py/sopdsdb.py b/py/sopdsdb.py deleted file mode 100644 index 77c4de2b59bb2d20993cd8077f7fb33b48362a86..0000000000000000000000000000000000000000 --- a/py/sopdsdb.py +++ /dev/null @@ -1,902 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -import sys -import mysql.connector -from mysql.connector import errorcode - -########################################################################## -# Наименования таблиц БД -# -DB_PREFIX="" -TBL_BOOKS=DB_PREFIX+"books" -TBL_CATALOGS=DB_PREFIX+"catalogs" -TBL_AUTHORS=DB_PREFIX+"authors" -TBL_BAUTHORS=DB_PREFIX+"bauthors" -TBL_GENRES=DB_PREFIX+"genres" -TBL_BGENRES=DB_PREFIX+"bgenres" -TBL_SERIES=DB_PREFIX+"series" -TBL_BSERIES=DB_PREFIX+"bseries" -TBL_BOOKSHELF=DB_PREFIX+"bookshelf" - -########################################################################## -# типы каталогов (cat_type) -# -CAT_NORMAL=0 -CAT_ZIP=1 -CAT_GZ=2 - -########################################################################## -# Как будем искать дубликаты -# -CMP_NONE=0 -CMP_NORMAL=1 -CMP_STRONG=2 -CMP_CLEAR=3 -CMP_TITLE_FTYPE_FSIZE=2 -CMP_TITLE_AUTHORS=1 - -########################################################################## -# разные константы -# -unknown_genre='Неизвестный жанр' - - -########################################################################### -# Класс доступа к MYSQL -# - -class opdsDatabase: - def __init__(self,iname,iuser,ipass,ihost,iroot_lib): - self.db_name=iname - self.db_user=iuser - self.db_pass=ipass - self.db_host=ihost - self.errcode=0 - self.err="" - self.isopen=False - self.next_page=False - self.root_lib=iroot_lib - - def openDB(self): - if not self.isopen: - try: - # buffered=true сделано для того чтобы избежать выборки fetchall при поиске книг и тэгов - self.cnx = mysql.connector.connect(user=self.db_user, password=self.db_pass, host=self.db_host, database=self.db_name, buffered=True) - except mysql.connector.Error as err: - if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: - self.err="Something is wrong with your user name or password" - self.errcode=1 - elif err.errno == errorcode.ER_BAD_DB_ERROR: - self.err="Database does not exists" - self.errcode=2 - else: - self.err=err - self.errcode=3 - else: - self.isopen=True - else: - self.errcode=4 - self.err="Error open database. Database Already open." - - def closeDB(self): - if self.isopen: - self.cnx.close() - self.isopen=False - else: - self.errcode=5 - self.err="Attempt to close not opened database." - - def printDBerr(self): - if self.errcode==0: - print("No Database Error found.") - else: - print("Error Code =",self.errcode,". Error Message:",self.err) - - def clearDBerr(self): - self.err="" - self.errcode=0 - - def findbook(self, name, path, setavail=0): - # Здесь специально не делается проверка avail, т.к. если удаление было логическим, а книга была восстановлена в своем старом месте - # то произойдет восстановление записи об этой книги а не добавится новая - sql_findbook=("select book_id from "+TBL_BOOKS+" where filename=%s and path=%s") - data_findbook=(name,path) - cursor=self.cnx.cursor() - cursor.execute(sql_findbook,data_findbook) - row=cursor.fetchone() - cursor.close() - if row==None: - book_id=0 - else: - book_id=row[0] - if setavail: - sql='update '+TBL_BOOKS+' set avail=2 where book_id=%s'%(book_id) - cursor=self.cnx.cursor() - cursor.execute(sql) - cursor.close() - return book_id - -# def finddouble(self,title,format,file_size): -# sql_findbook=("select book_id from "+TBL_BOOKS+" where title=%s and format=%s and filesize=%s and avail!=0 and doublicat=0") -# data_findbook=(title,format,file_size) -# cursor=self.cnx.cursor() -# cursor.execute(sql_findbook,data_findbook) -# row=cursor.fetchone() -# if row==None: -# book_id=0 -# else: -# book_id=row[0] -# cursor.close() -# return book_id - - def findbookshelf(self,user,book_id): - sql=("select book_id from "+TBL_BOOKSHELF+" where user=%s and book_id=%s") - data=(user,book_id) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - row=cursor.fetchone() - if row==None: - book_id=0 - else: - book_id=row[0] - cursor.close() - return book_id - - def addbookshelf(self,user,book_id): - if self.findbookshelf(user,book_id)==0: - sql=("insert into "+TBL_BOOKSHELF+"(user,book_id) VALUES(%s, %s)") - data=(user,book_id) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - self.cnx.commit() - book_id=cursor.lastrowid - cursor.close() - return book_id - - def addbook(self, name, path, cat_id, exten, title, annotation, docdate, lang, size=0, archive=0, doublicates=0): - format=exten[1:] - format=format.lower() -# if doublicates!=0: -# doublicat=self.finddouble(title,format,size) -# else: - doublicat=0 - sql_addbook=("insert into "+TBL_BOOKS+"(filename,path,cat_id,filesize,format,title,annotation,docdate,lang,cat_type,doublicat,avail) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 2)") - data_addbook=(name,path,cat_id,size,format,title,annotation,docdate,lang,archive,doublicat) - cursor=self.cnx.cursor() - cursor.execute(sql_addbook,data_addbook) - book_id=cursor.lastrowid - cursor.close() - return book_id - -# def addcover(self,book_id,fn,cover_type): -# sql=("update "+TBL_BOOKS+" set cover=%s, cover_type=%s where book_id=%s") -# data=(fn,cover_type,book_id) -# cursor=self.cnx.cursor() -# cursor.execute(sql,data) -# cursor.close() - - def findauthor(self,first_name,last_name): - sql_findauthor=("select author_id from "+TBL_AUTHORS+" where last_name=%s and first_name=%s LIMIT 1") - data_findauthor=(last_name,first_name) - cursor=self.cnx.cursor() - cursor.execute(sql_findauthor,data_findauthor) - row=cursor.fetchone() - if row==None: - author_id=0 - else: - author_id=row[0] - cursor.close() - return author_id - - def findbauthor(self, book_id, author_id): - sql_findbauthor=("select book_id from "+TBL_BAUTHORS+" where book_id=%s and author_id=%s") - data_findbauthor=(book_id,author_id) - cursor=self.cnx.cursor() - cursor.execute(sql_findbauthor,data_findbauthor) - row=cursor.fetchone() - result=(row!=None) - cursor.close() - return result - - def addauthor(self, first_name, last_name): - author_id=self.findauthor(first_name,last_name) - if author_id!=0: - return author_id - sql_addauthor=("insert into "+TBL_AUTHORS+"(first_name,last_name) VALUES(%s,%s)") - data_addauthor=(first_name,last_name) - cursor=self.cnx.cursor() - cursor.execute(sql_addauthor,data_addauthor) - author_id=cursor.lastrowid - cursor.close() - return author_id - - def addbauthor(self, book_id, author_id): - sql_addbauthor=("insert into "+TBL_BAUTHORS+"(book_id,author_id) VALUES(%s,%s)") - data_addbauthor=(book_id,author_id) - cursor=self.cnx.cursor() - try: - cursor.execute(sql_addbauthor,data_addbauthor) - except: - pass - finally: - cursor.close() - - def findgenre(self,genre): - sql=("select genre_id from "+TBL_GENRES+" where genre='"+genre+"'") - cursor=self.cnx.cursor() - cursor.execute(sql) - row=cursor.fetchone() - if row==None: - genre_id=0 - else: - genre_id=row[0] - cursor.close() - return genre_id - - def findbgenre(self, book_id, genre_id): - sql=("select book_id from "+TBL_BGENRES+" where book_id=%s and genre_id=%s") - data=(book_id,genre_id) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - row=cursor.fetchone() - result=(row!=None) - cursor.close() - return result - - def addgenre(self, genre): - genre_id=self.findgenre(genre) - if genre_id!=0: - return genre_id - sql=("insert into "+TBL_GENRES+"(genre,section,subsection) VALUES(%s,%s,%s)") - data=(genre,unknown_genre,genre) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - genre_id=cursor.lastrowid - cursor.close() - return genre_id - - def addbgenre(self, book_id, genre_id): - sql=("insert into "+TBL_BGENRES+"(book_id,genre_id) VALUES(%s,%s)") - data=(book_id,genre_id) - cursor=self.cnx.cursor() - try: - cursor.execute(sql,data) - except: - pass - finally: - cursor.close() - - def findseries(self,ser): - sql=("select ser_id from "+TBL_SERIES+" where ser=%s") - data=(ser,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - row=cursor.fetchone() - if row==None: - ser_id=0 - else: - ser_id=row[0] - cursor.close() - return ser_id - - def findbseries(self, book_id, ser_id): - sql=("select book_id from "+TBL_BSERIES+" where book_id=%s and ser_id=%s") - data=(book_id,ser_id) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - row=cursor.fetchone() - result=(row!=None) - cursor.close() - return result - - def addseries(self, ser): - ser_id=self.findseries(ser) - if ser_id!=0: - return ser_id - sql=("insert into "+TBL_SERIES+"(ser) VALUES(%s)") - data=(ser,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - ser_id=cursor.lastrowid - cursor.close() - return ser_id - - def addbseries(self, book_id, ser_id, ser_no): - sql=("insert into "+TBL_BSERIES+"(book_id,ser_id,ser_no) VALUES(%s,%s,%s)") - data=(book_id,ser_id,ser_no) - cursor=self.cnx.cursor() - try: - cursor.execute(sql,data) - except: - pass - finally: - cursor.close() - - def findcat(self, catalog): - (head,tail)=os.path.split(catalog) - sql_findcat=("select cat_id from "+TBL_CATALOGS+" where cat_name=%s and path=%s") - data_findcat=(tail,catalog) - cursor=self.cnx.cursor() - cursor.execute(sql_findcat,data_findcat) - row=cursor.fetchone() - if row==None: - cat_id=0 - else: - cat_id=row[0] - cursor.close() - return cat_id - - def addcattree(self, catalog, archive=0): - cat_id=self.findcat(catalog) - if cat_id!=0: - return cat_id - if catalog=="": - return 0 - (head,tail)=os.path.split(catalog) - parent_id=self.addcattree(head) - sql_addcat=("insert into "+TBL_CATALOGS+"(parent_id,cat_name,path,cat_type) VALUES(%s, %s, %s, %s)") - data_addcat=(parent_id,tail,catalog,archive) - cursor=self.cnx.cursor() - cursor.execute(sql_addcat,data_addcat) - cat_id=cursor.lastrowid - cursor.close() - return cat_id - - def getcatinparent(self,parent_id,limit=0,page=0): - if limit==0: - limitstr="" - else: - limitstr="limit "+str(limit*page)+","+str(limit) - sql_findcats=("select cat_id,cat_name from "+TBL_CATALOGS+" where parent_id="+str(parent_id)+" order by cat_name "+limitstr) - cursor=self.cnx.cursor() - cursor.execute(sql_findcats) - rows=cursor.fetchall() - cursor.close - return rows - - def getbooksincat(self,cat_id,limit=0,page=0): - if limit==0: - limitstr="" - else: - limitstr="limit "+str(limit*page)+","+str(limit) - sql_findbooks=("select book_id,filename, path, registerdate from "+TBL_BOOKS+" where cat_id="+str(cat_id)+" and avail!=0 order by filename "+limitstr) - cursor=self.cnx.cursor() - cursor.execute(sql_findbooks) - rows=cursor.fetchall() - cursor.close - return rows - - def getitemsincat(self,cat_id,limit=0,page=0): - if limit==0: - limitstr="" - else: - limitstr="limit "+str(limit*page)+","+str(limit) - sql_finditems=("select SQL_CALC_FOUND_ROWS 1,cat_id,cat_name,path,now(),cat_name as title,'' as docdate,'' as annotation,'cat' as format, 0 as filesize, '' as cover, '' as cover_type from "+TBL_CATALOGS+" where parent_id="+str(cat_id)+" union all " - "select 2,book_id,filename,path,registerdate,title,annotation,docdate,format,filesize,cover,cover_type from "+TBL_BOOKS+" where cat_id="+str(cat_id)+" and avail!=0 order by 1,6 "+limitstr) - cursor=self.cnx.cursor() - cursor.execute(sql_finditems) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getbook(self,book_id): - sql_getbook=("select filename, path, registerdate, format, title, annotation, docdate,cat_type, cover, cover_type, filesize from "+TBL_BOOKS+" where book_id="+str(book_id)+" and avail!=0") - cursor=self.cnx.cursor() - cursor.execute(sql_getbook) - row=cursor.fetchone() - cursor.close - return row - - def getauthors(self,book_id): - sql=("select a.author_id,first_name,last_name from "+TBL_AUTHORS+" a, "+TBL_BAUTHORS+" b where b.author_id=a.author_id and b.book_id="+str(book_id)) - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - cursor.close - return rows - - def getauthor_name(self, author_id): - sql=("select first_name,last_name from "+TBL_AUTHORS+" where author_id=%s") - data=(author_id,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - row=cursor.fetchone() - cursor.close - return row - - def getser_name(self, ser_id): - sql=("select ser from "+TBL_SERIES+" where ser_id=%s") - data=(ser_id,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - row=cursor.fetchone() - cursor.close - return row - - def getgenres(self,book_id): - sql=("select a.genre_id, section, subsection from "+TBL_GENRES+" a, "+TBL_BGENRES+" b where b.genre_id=a.genre_id and b.book_id="+str(book_id)) - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - cursor.close - return rows - - def getseries(self,book_id): - sql=("select a.ser_id, a.ser, b.ser_no from "+TBL_SERIES+" a, "+TBL_BSERIES+" b where b.ser_id=a.ser_id and b.book_id="+str(book_id)) - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - cursor.close - return rows - - def getauthor_2letters(self,letters,alpha=0,new_period=0): - lc=len(letters)+1 - having='' - if lc==1: - if alpha==1: having=" having INSTR('АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ',letters)>0 and letters!=''" - elif alpha==2: having=" having INSTR('0123456789',letters)>0 and letters!=''" - elif alpha==3: having=" having INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZ',letters)>0 and letters!=''" - elif alpha==4: having=" having INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ0123456789',letters)=0 and letters!=''" - if new_period==0: period='' - else: period="and author_id in (select b.author_id from bauthors b left join books c on b.book_id=c.book_id where registerdate>now()-INTERVAL %s DAY group by b.author_id)"%new_period - sql="select UPPER(substring(CONCAT(last_name,' ',first_name),1,"+str(lc)+")) as letters, count(*) as cnt from "+TBL_AUTHORS+" where CONCAT(last_name,' ',first_name) like %s "+period+" group by CONCAT(letters,'-')"+having+" order by 1" - data=(letters+'%',) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - cursor.close - return rows - - def gettitle_2letters(self,letters,doublicates=True,alpha=0,new_period=0): - if doublicates: dstr="" - else: dstr=" and doublicat=0 " - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY)"%new_period - lc=len(letters)+1 - having='' - if lc==1: - if alpha==1: having=" having INSTR('АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ',letters)>0 and letters!=''" - elif alpha==2: having=" having INSTR('0123456789',letters)>0 and letters!=''" - elif alpha==3: having=" having INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZ',letters)>0 and letters!=''" - elif alpha==4: having=" having INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ0123456789',letters)=0 and letters!=''" - - sql="select UPPER(substring(title,1,"+str(lc)+")) as letters, count(*) as cnt from "+TBL_BOOKS+" where title like %s and avail!=0 "+dstr+period+" group by CONCAT(letters,'-')"+having+" order by 1" - data=(letters+'%',) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - cursor.close - return rows - - def getseries_2letters(self,letters,alpha=0,new_period=0): - lc=len(letters)+1 - having='' - if lc==1: - if alpha==1: having=" having INSTR('АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ',letters)>0 and letters!=''" - elif alpha==2: having=" having INSTR('0123456789',letters)>0 and letters!=''" - elif alpha==3: having=" having INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZ',letters)>0 and letters!=''" - elif alpha==4: having=" having INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ0123456789',letters)=0 and letters!=''" - if new_period==0: period='' - else: period="and ser_id in (select b.ser_id from bseries b left join books c on b.book_id=c.book_id where registerdate>now()-INTERVAL %s DAY group by b.ser_id)"%new_period - - sql="select UPPER(substring(ser,1,"+str(lc)+")) as letters, count(*) as cnt from "+TBL_SERIES+" where ser like %s "+period+" group by CONCAT(letters,'-')"+having+" order by 1" - data=(letters+'%',) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - cursor.close - return rows - - - def getbooksfortitle(self,letters,limit=0,page=0,doublicates=True,new_period=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and doublicat=0' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY)"%new_period - sql="select SQL_CALC_FOUND_ROWS book_id,filename,path,registerdate,title,annotation,docdate,format,filesize,cover,cover_type from "+TBL_BOOKS+" where title like %s and avail!=0"+dstr+period+" order by title "+limitstr - data=(letters+'%',) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getdoublecount(self,id): - sql='select count(*) from '+TBL_BOOKS+' where doublicat=%s' - data=(id,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - - row=cursor.fetchone() - if row==None: - dcount=0 - else: - dcount=row[0] - cursor.close() - return dcount - - def getdoubles(self,id,limit=0,page=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - sql="select SQL_CALC_FOUND_ROWS book_id,filename,path,registerdate,title,annotation,docdate,format,filesize,cover,cover_type from "+TBL_BOOKS+" where doublicat=%s and avail!=0 order by docdate "+limitstr - data=(id,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getauthorsbyl(self,letters,limit=0,page=0,doublicates=True,new_period=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and c.doublicat=0 ' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY) and a.author_id in (select b.author_id from bauthors b left join books c on b.book_id=c.book_id where registerdate>now()-INTERVAL %s DAY group by b.author_id)"%(new_period,new_period) - - sql="select SQL_CALC_FOUND_ROWS a.author_id, a.first_name, a.last_name, count(*) as cnt from "+TBL_AUTHORS+" a, "+TBL_BAUTHORS+" b, "+TBL_BOOKS+" c where a.author_id=b.author_id and b.book_id=c.book_id and CONCAT(a.last_name,' ',a.first_name) like %s and c.avail!=0 "+dstr+period+" group by 1,2,3 order by 3,2 "+limitstr - data=(letters+'%',) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getbooksforautor(self,author_id,limit=0,page=0,doublicates=True,new_period=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and a.doublicat=0 ' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY)"%new_period - sql="select SQL_CALC_FOUND_ROWS a.book_id,a.filename,a.path,a.registerdate,a.title,a.annotation,a.docdate,a.format,a.filesize,a.cover,a.cover_type from "+TBL_BOOKS+" a, "+TBL_BAUTHORS+" b where a.book_id=b.book_id and b.author_id="+str(author_id)+" and a.avail!=0 "+dstr+period+" order by a.title "+limitstr - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getbooksforautorser(self,author_id,ser_id,limit=0,page=0,doublicates=True): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and a.doublicat=0 ' - if ser_id!=0: - sql=("select SQL_CALC_FOUND_ROWS a.book_id,a.filename,a.path,a.registerdate,a.title,a.annotation,a.docdate,a.format,a.filesize,a.cover,a.cover_type " - "from "+TBL_BOOKS+" a " - "left join "+TBL_BAUTHORS+" b on a.book_id=b.book_id " - "left join "+TBL_BSERIES +" c on a.book_id=c.book_id " - "where author_id=%s and ser_id=%s and a.avail!=0 "+dstr+" order by c.ser_no, a.title "+limitstr) - data=(author_id,ser_id) - else: - sql=("select SQL_CALC_FOUND_ROWS a.book_id,a.filename,a.path,a.registerdate,a.title,a.annotation,a.docdate,a.format,a.filesize,a.cover,a.cover_type " - "from "+TBL_BOOKS+" a " - "left join "+TBL_BAUTHORS+" b on a.book_id=b.book_id " - "left outer join "+TBL_BSERIES +" c on a.book_id=c.book_id " - "where author_id=%s and ser_id is NULL and a.avail!=0 "+dstr+" order by a.title "+limitstr) - data=(author_id,) - - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getseriesforauthor(self,author_id,limit=0,page=0,doublicates=True): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and doublicat=0 ' - - sql=("select SQL_CALC_FOUND_ROWS a.ser_id, a.ser, count(*) from "+TBL_SERIES+" a " - "left join "+TBL_BSERIES+" b on a.ser_id=b.ser_id " - "left join "+TBL_BAUTHORS+" c on b.book_id=c.book_id " - "left join "+TBL_BOOKS+" d on b.book_id=d.book_id " - "where author_id=%s and avail!=0 "+dstr+" group by 1,2 order by a.ser "+limitstr) - data=(author_id,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getseriesbyl(self,letters,limit=0,page=0,doublicates=True,new_period=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and c.doublicat=0 ' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY) and a.ser_id in (select b.ser_id from bseries b left join books c on b.book_id=c.book_id where registerdate>now()-INTERVAL %s DAY group by b.ser_id)"%(new_period,new_period) - sql="select SQL_CALC_FOUND_ROWS a.ser_id, a.ser, count(*) as cnt from "+TBL_SERIES+" a, "+TBL_BSERIES+" b, "+TBL_BOOKS+" c where a.ser_id=b.ser_id and b.book_id=c.book_id and a.ser like %s and c.avail!=0 "+dstr+period+" group by 1,2 order by 2 "+limitstr - data=(letters+'%',) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getbooksforser(self,ser_id,limit=0,page=0,doublicates=True,new_period=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and a.doublicat=0 ' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY)"%new_period - sql="select SQL_CALC_FOUND_ROWS a.book_id,a.filename,a.path,a.registerdate,a.title,a.annotation,a.docdate,a.format,a.filesize,a.cover,a.cover_type from "+TBL_BOOKS+" a, "+TBL_BSERIES+" b where a.book_id=b.book_id and b.ser_id="+str(ser_id)+" and a.avail!=0 "+dstr+period+" order by b.ser_no, a.title "+limitstr - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - - def getlastbooks(self,limit=0): - if limit==0: - limitstr="" - else: - limitstr="limit "+str(limit) - sql="select book_id,filename,path,registerdate,title,annotation,docdate,format,filesize,cover,cover_type from "+TBL_BOOKS+" where avail!=0 order by registerdate desc "+limitstr - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - cursor.close - return rows - - def getgenres_sections(self,doublicates=True,new_period=0): - if doublicates: dstr='' - else: dstr=' and c.doublicat=0 ' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY)"%new_period - if new_period==0: - sql="select min(a.genre_id), a.section, count(*) as cnt from "+TBL_GENRES+" a, "+TBL_BGENRES+" b where a.genre_id=b.genre_id group by a.section order by a.section" - else: - sql="select min(a.genre_id), a.section, count(*) as cnt from "+TBL_GENRES+" a, "+TBL_BGENRES+" b, "+TBL_BOOKS+" c where a.genre_id=b.genre_id and b.book_id=c.book_id and c.avail!=0 "+dstr+period+" group by a.section order by a.section" - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - cursor.close - return rows - - def getgenres_subsections(self,section_id,doublicates=True,new_period=0): - if doublicates: dstr='' - else: dstr=' and c.doublicat=0 ' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY)"%new_period - if new_period==0: - sql="select a.genre_id, a.subsection, count(*) as cnt from "+TBL_GENRES+" a, "+TBL_BGENRES+" b where a.genre_id=b.genre_id and section in (select section from "+TBL_GENRES+" where genre_id="+str(section_id)+") group by a.subsection order by a.subsection" - else: - sql="select a.genre_id, a.subsection, count(*) as cnt from "+TBL_GENRES+" a, "+TBL_BGENRES+" b, "+TBL_BOOKS+" c where a.genre_id=b.genre_id and b.book_id=c.book_id and c.avail!=0 "+dstr+period+" and section in (select section from "+TBL_GENRES+" where genre_id="+str(section_id)+") group by a.subsection order by a.subsection" - - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - cursor.close - return rows - - def getbooksforgenre(self,genre_id,limit=0,page=0,doublicates=True,alpha=0,new_period=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - if doublicates: dstr='' - else: dstr=' and a.doublicat=0 ' - if new_period==0: period='' - else: period=" and (registerdate>now()-INTERVAL %s DAY)"%new_period - having='' - if alpha==1: having=" and INSTR('АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ',UPPER(substr(a.title,1,1)))>0" - elif alpha==2: having=" and INSTR('0123456789',UPPER(substr(a.title,1,1)))>0" - elif alpha==3: having=" and INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZ',UPPER(substr(a.title,1,1)))>0" - elif alpha==4: having=" and INSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ0123456789',UPPER(substr(a.title,1,1)))=0" - - sql="select SQL_CALC_FOUND_ROWS a.book_id,a.filename,a.path,a.registerdate,a.title,a.annotation,a.docdate,a.format,a.filesize,a.cover,a.cover_type from "+TBL_BOOKS+" a, "+TBL_BGENRES+" b where a.book_id=b.book_id and b.genre_id="+str(genre_id)+" and a.avail!=0 "+dstr+period+having+" order by a.lang, a.title "+limitstr - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getbooksforuser(self,user,limit=0,page=0): - if limit==0: limitstr="" - else: limitstr="limit "+str(limit*page)+","+str(limit) - sql="select SQL_CALC_FOUND_ROWS a.book_id,a.filename,a.path,a.registerdate,a.title,a.annotation,a.docdate,a.format,a.filesize,a.cover,a.cover_type from "+TBL_BOOKS+" a, "+TBL_BOOKSHELF+" b where a.book_id=b.book_id and b.user=%s and a.avail!=0 order by readtime desc "+limitstr - data=(user,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - rows=cursor.fetchall() - - cursor.execute("SELECT FOUND_ROWS()") - found_rows=cursor.fetchone() - if found_rows[0]>limit*page+limit: - self.next_page=True - else: - self.next_page=False - - cursor.close - return rows - - def getdbinfo(self,doublicates=True,book_shelf=False, user=None): - if doublicates: dstr='' - else: dstr='and doublicat=0' - if book_shelf and user!=None: bs=" union all select 6 s, count(book_id) from "+TBL_BOOKSHELF+" where user='"+user+"' " - else: bs="" - - sql="select 1 s, count(avail) from %s where avail!=0 %s union all select 2 s, count(author_id) from %s union all select 3 s, count(cat_id) from %s union all select 4 s, count(genre_id) from %s union all select 5 s, count(ser_id) from %s %s order by s"%(TBL_BOOKS,dstr,TBL_AUTHORS,TBL_CATALOGS,TBL_GENRES,TBL_SERIES,bs) - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - cursor.close - return rows - - def getnewinfo(self,doublicates=True,new_period=0): - if doublicates: dstr='' - else: dstr='and doublicat=0' - - if new_period==0: period='' - else: period='and registerdate>now()-INTERVAL %s DAY'%new_period - - sql="select 1 s, count(avail) from %s where avail!=0 %s %s"%(TBL_BOOKS,dstr,period) - cursor=self.cnx.cursor() - cursor.execute(sql) - rows=cursor.fetchall() - - cursor.close - return rows - - def zipisscanned(self,zipname,setavail=0): - sql='select cat_id from '+TBL_BOOKS+' where path="'+zipname+'" limit 1' - cursor=self.cnx.cursor() - cursor.execute(sql) - row=cursor.fetchone() - cursor.close - if row==None: - cat_id=0 - else: - cat_id=row[0] - if setavail: - sql='update '+TBL_BOOKS+' set avail=2 where cat_id=%s'%(cat_id) - cursor=self.cnx.cursor() - cursor.execute(sql) - cursor.close() - return cat_id - -# Книги где avail=0 уже известно что удалены -# Книги где avail=2 это только что прверенные существующие книги -# Устанавливаем avail=1 для книг которые не удалены. Во время проверки если они не удалены им присвоится значение 2 -# Книги с avail=0 проверятся не будут и будут убраны из всех выдач и всех обработок. -# -# три позиции (0,1,2) сделаны для того чтобы сделать возможным корректную работу cgi-скрипта во время сканирования библиотеки -# - def avail_check_prepare(self): - sql='update '+TBL_BOOKS+' set avail=1 where avail!=0' - cursor=self.cnx.cursor() - cursor.execute(sql) - self.cnx.commit() - cursor.close - - def books_del_logical(self): - sql='update '+TBL_BOOKS+' set avail=0 where avail=1' - cursor=self.cnx.cursor() - cursor.execute(sql) - cursor.execute("SELECT ROW_COUNT()") - row_count=cursor.fetchone()[0] - self.cnx.commit() - cursor.close - return row_count - - def books_del_phisical(self): - cursor=self.cnx.cursor() - sql='delete from '+TBL_BAUTHORS+' where book_id in (select book_id from '+TBL_BOOKS+' where avail<=1)' - cursor.execute(sql) - sql='delete from '+TBL_BGENRES+' where book_id in (select book_id from '+TBL_BOOKS+' where avail<=1)' - cursor.execute(sql) - - sql='delete from '+TBL_BOOKS+' where avail<=1' - cursor.execute(sql) - cursor.execute("SELECT ROW_COUNT()") - row_count=cursor.fetchone()[0] - self.cnx.commit() - cursor.close - return row_count - -# def update_double(self): -# sql='call sp_update_dbl()' -# cursor=self.cnx.cursor() -# cursor.execute(sql) -# self.cnx.commit() -# cursor.close - - def mark_double(self, cmp_type=CMP_NORMAL): - sql='call sp_mark_dbl(%s)' - data=(cmp_type,) - cursor=self.cnx.cursor() - cursor.execute(sql,data) - self.cnx.commit() - cursor.close - - def commit(self): - self.cnx.commit() - - def __del__(self): - self.closeDB() - diff --git a/py/sopdserve.py b/py/sopdserve.py deleted file mode 100755 index 225f55e47e5109bc764fd27251f6507aacfefe0d..0000000000000000000000000000000000000000 --- a/py/sopdserve.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import base64 -from urllib import parse -from wsgiref.simple_server import make_server -from wsgiref.simple_server import WSGIRequestHandler -import sopdscli -import sopdscfg -import zipf - -sopds = None -cfg = None - -#class opdsHandler(WSGIRequestHandler): -# def get_stderr(self): -# se = open(cfg.HTTPD_LOGFILE, 'a+') -# return se.fileno() - -def authorized_user(auth_list, auth_data): - user=None - alist=auth_list.split() - for ainfo in alist: - acode='Basic %s'%base64.encodestring(ainfo.strip().encode()).decode().strip() - if acode==auth_data.strip(): - (user,pw)=ainfo.split(':') - return user - -def app(environ, start_response): - sopds.resetParams() - user=None - if 'HTTP_AUTHORIZATION' in environ: - adata=environ['HTTP_AUTHORIZATION'] - user=authorized_user(cfg.ACCOUNTS,adata) - - if (user!=None) or not cfg.AUTH: - sopds.resetParams() - sopds.parseParams(environ) - sopds.setUser(user) - sopds.make_response() - else: - sopds.set_response_status('401 Unauthorized') - sopds.add_response_header([('WWW-Authenticate', 'Basic realm=\"%s\"'%cfg.SITE_TITLE)]) - sopds.add_response_header([('Content-type', 'text/html')]) - - start_response(sopds.get_response_status(), sopds.get_response_headers()) - return sopds.get_response_body() - -def start_server(config): - global sopds - global cfg - - cfg=config - zipf.ZIP_CODEPAGE=cfg.ZIP_CODEPAGE - sopds = sopdscli.opdsClient(cfg,sopdscli.modeINT) - - try: - httpd = make_server(cfg.BIND_ADDRESS, cfg.PORT, app) - print('Started Simple OPDS server on port ' , cfg.PORT) - httpd.serve_forever() - except KeyboardInterrupt: - print('^C received, shutting down the web server') - httpd.socket.close() - - -if __name__ == "__main__": - config=sopdscfg.cfgreader() - start_server(config) diff --git a/py/sopdstempl.py b/py/sopdstempl.py deleted file mode 100644 index 09f149547cd92864c8382e92e26de0fbb68398d1..0000000000000000000000000000000000000000 --- a/py/sopdstempl.py +++ /dev/null @@ -1,345 +0,0 @@ -class opdsTemplate(): - def __init__(self,charset='utf-8'): - self.response_header=('Content-Type','text/xml; charset='+charset) - self.opensearch=('' - '' - 'SimpleOPDS' - 'SimpleOPDS' - '' - 'http://www.sopds.ru/favicon.ico' - '' - '' - '' - '' - 'open' - 'false' - '*' - 'UTF-8' - 'UTF-8' - '') - self.opensearch_forms=('Поиск книгid:search:71Поиск книги по ее наименованию' - '' - '' - 'Поиск авторовid:search:72Поиск авторов по имени' - '' - '' - 'Поиск серийid:search:73Поиск серий книг' - '' - '') - - self.agregate_authors=('%(last_name)s %(first_name)s') - self.agregate_authors_link=('') - self.agregate_genres='' - self.agregate_genres_link='' - self.agregate_series='' - self.agregate_series_link='' - - self.document_style='' - self.document_header=('' - '' - '%(page_id)s' - '%(page_title)s' - '%(site_subtitle)s' - '%(page_updated)s' - '%(site_icon)s' - '%(site_author)s%(site_url)s%(site_email)s') - self.document_footer='' - - self.page_top_start='' - self.page_top_linkstart='' - self.page_top_linkself='' - self.page_top_linksearch=( -# '' - '') - self.page_top_finish='' - - self.page_bottom_start='' - self.page_bottom_info='' - self.page_bottom_finish='' - - self.page_title_start='' - self.page_title_info='' - self.page_title_finish='' - - self.document_mainmenu_std=( - '' - 'По каталогам' - 'Каталогов: %(cat_num)s, книг: %(book_num)s.' - '' - 'id:01' - '' - 'По авторам' - 'Авторов: %(author_num)s.' - '' - 'id:02' - '' - 'По наименованию' - 'Книг: %(book_num)s.' - '' - 'id:03' - '' - 'По Жанрам' - 'Жанров: %(genre_num)s.' - '' - 'id:04' - '' - 'По Сериям' - 'Серий: %(series_num)s.' - '' - 'id:06' - ) - self.document_mainmenu_new=('' - 'Новинки за %(new_period)s суток' - '' - 'id:05' - ) - self.document_mainmenu_shelf=('' - 'Книжная полка для %(user)s' - 'Книг: %(shelf_book_num)s.' - '' - 'id:08' - ) - self.document_newmenu=('' - 'Все новинки за %(new_period)s суток' - 'Новых книг: %(newbook_num)s.' - '' - 'id:03:news' - '' - 'Новинки по авторам' - '' - 'id:02:news' - '' - 'Новинки по Жанрам' - '' - 'id:04:news' - '' - 'Новинки по Сериям' - '' - 'id:06:news' - ) - self.document_authors_submenu=('' - 'Книги по сериям' - '' - 'id:31:authors' - '' - 'Книги вне серий' - '' - 'id:32:authors' - '' - 'Книги по алфавиту' - '' - 'id:33:authors' - ) - - self.document_alphabet_menu=('А..Я (РУС)alpha:1' - '0..9 (Цифры)alpha:2' - 'A..Z (ENG)alpha:3' - 'Другие Символыalpha:4' - 'Показать всеalpha:5' - ) - self.document_page_control_start='' - self.document_page_control_prev=('' - ) - self.document_page_control_next=('' - ) - self.document_page_control_finish='' - - self.document_entry_nav_start='' - self.document_entry_nav_title=('%(e_title)s' - '%(e_date)s' - 'id:%(e_id)s') - self.document_entry_nav_link=('' -# '' - ) - self.document_entry_nav_info=('%(e_nav_info)s') - self.document_entry_nav_finish='' - - self.document_entry_acq_start='' - self.document_entry_acq_link_start='' - self.document_entry_acq_book_title=('%(e_title)s' - '%(e_date)s' - 'id:%(e_id)s') - self.document_entry_acq_book_link_alternate='' -# ('' -# ) - self.document_entry_acq_book_link=('' - ) - self.document_entry_acq_link_finish='' - - self.document_entry_acq_info_start='' - - self.document_entry_acq_info_cover=('' - '' - '' - '' - ) - - self.document_entry_acq_infobook_start='' - self.document_entry_acq_infobook_title='<b>Название книги:</b> %(e_title)s<br/>' - self.document_entry_acq_infobook_authors='<b>Авторы:</b> %(authors)s<br/>' - self.document_entry_acq_infobook_genres='<b>Жанры:</b> %(genres)s<br/>' - self.document_entry_acq_infobook_series='<b>Серии:</b> %(series)s<br/>' - self.document_entry_acq_infobook_filename='<b>Файл:</b> %(filename)s<br/>' - self.document_entry_acq_infobook_filesize='<b>Размер файла:</b> %(filesize)sКб.<br/>' - self.document_entry_acq_infobook_docdate='<b>Дата правки:</b> %(docdate)s<br/>' - self.document_entry_acq_infobook_annotation='<p class=book> %(annotation)s</p>' - self.document_entry_acq_infobook_userdata='' - self.document_entry_acq_infobook_finish='' - self.document_entry_acq_rel_start='' - self.document_entry_acq_rel_doubles=('' - ) - self.document_entry_acq_rel_authors='%(authors)s %(authors_link)s' - self.document_entry_acq_rel_genres='%(genres)s' - self.document_entry_acq_rel_finish='' - self.document_entry_acq_info_finish='' - self.document_entry_acq_finish='' - - -class webTemplate(opdsTemplate): - def __init__(self,charset='utf-8'): - self.response_header=('Content-Type','text/html; charset='+charset) - - self.opensearch='' - self.opensearch_forms=('Поиск книг
' - 'Поиск авторов
' - 'Поиск серий
') - -################################################################################################################################### -# Шаблоны для Агрегации внутри Acquisition Entry -# - - self.agregate_authors=('%(last_name)s %(first_name)s, ') - self.agregate_authors_link=('%(last_name)s %(first_name)s, ' - ) - self.agregate_genres='%(genre)s, ' - self.agregate_genres_link=('%(genre)s, ' - ) - self.agregate_series='%(ser)s #%(ser_no)s, ' - self.agregate_series_link=('%(ser)s #%(ser_no)s, ' - ) - - self.document_style=''' - - ''' - self.document_header=('' - '' - '' - '%(site_title)s' - '%(style)s' - '' - '') - self.document_footer='' - - self.page_top_start='
' - self.page_top_linkstart='SOPDS.RU Главнaя ' - self.page_top_linkself='' - self.page_top_linksearch='Поиск ' - self.page_top_finish='' - - self.page_bottom_start='' - self.page_bottom_info='' - self.page_bottom_finish='
' - - self.page_title_start='' - self.page_title_info='

%(page_title)s

' - self.page_title_finish='' - - - self.document_mainmenu_std=('

По каталогам

  Каталогов: %(cat_num)s, книг: %(book_num)s.
' - '

По авторам

  Авторов: %(author_num)s.
' - '

По наименованию

  Книг: %(book_num)s.
' - '

По жанрам

  Жанров: %(genre_num)s.
' - '

По сериям

  Серий: %(series_num)s.
' - ) - self.document_mainmenu_new=('

Новинки за %(new_period)s суток.

' - ) - self.document_mainmenu_shelf=('

Книжная полка для %(user)s.

' - ) - self.document_newmenu=('

Все новинки за %(new_period)s суток

' - '

Новинки по авторам

' - '

Новинки по Жанрам

' - '

Новинки по Сериям

' - ) - self.document_authors_submenu=('

Книги по сериям

' - '

Книги вне серий

' - '

Книги по алфавиту

' - ) - - self.document_alphabet_menu=('

А..Я (РУС)

' - '

0..9 (Цифры)

' - '

A..Z (ENG)

' - '

Другие символы

' - '

Показать все

' - ) - self.document_page_control_start='
' - - self.document_page_control_prev=(' <Предыдущая страница ' - ) - self.document_page_control_next=(' Следующая страница>' - ) - self.document_page_control_finish='
' - - self.document_entry_nav_start='
\n' - self.document_entry_nav_title='' - self.document_entry_nav_link=('

%(e_title)s

' - ) - self.document_entry_nav_info=('  %(e_nav_info)s') - self.document_entry_nav_finish='
' - - - self.document_entry_acq_start='
\n' - self.document_entry_acq_link_start='' - - self.document_entry_acq_info_start='
\n' - - self.document_entry_acq_info_cover=('
' - ) - - self.document_entry_acq_infobook_start='
' - self.document_entry_acq_infobook_title='Название книги: %(e_title)s
' - self.document_entry_acq_infobook_authors='Авторы: %(authors_link)s
' - self.document_entry_acq_infobook_genres='Жанры: %(genres_link)s
' - self.document_entry_acq_infobook_series='Серии: %(series_link)s
' - self.document_entry_acq_infobook_filename='Файл: %(filename)s
' - self.document_entry_acq_infobook_filesize='Размер файла: %(filesize)sКб.
' - self.document_entry_acq_infobook_docdate='Дата правки: %(docdate)s
' - self.document_entry_acq_infobook_annotation='

%(annotation)s

' - self.document_entry_acq_infobook_userdata='' - self.document_entry_acq_infobook_finish='
' - - self.document_entry_acq_rel_start='
' - self.document_entry_acq_rel_doubles=('Дубликаты книги "%(e_title)s" (%(dcount)sшт.)' - ) - self.document_entry_acq_rel_authors='' - self.document_entry_acq_rel_genres='' - self.document_entry_acq_rel_finish='
' - - self.document_entry_acq_info_finish='
' - - self.document_entry_acq_finish='

' - diff --git a/py/sopdswrap.py b/py/sopdswrap.py deleted file mode 100644 index 8f06cb1b20b36d2b86d4f813680c96c786d68fc7..0000000000000000000000000000000000000000 --- a/py/sopdswrap.py +++ /dev/null @@ -1,221 +0,0 @@ -import sys -import sopdscfg -import sopdstempl -import datetime - -def websym(s,attr=False): - """Replace special web-symbols""" - result = s - if attr: - table = {'"':'\'','&':'&'} - else: - table = {'&':'&','<':'<'} - for k in table.keys(): - result = result.replace(k,table[k]) - return result; - -def dictmerge(a,b={},c={}): - data=a.copy() - data.update(b) - data.update(c) - return data - -####################################################################### -# -# Базовый класс формирующий вывод -# -class baseWrapper(): - def __init__(self, cfg, template, site_data): - self.cfg=cfg - self.site_data=site_data - self.template=template - self.response_status='200 Ok' - self.response_headers=[] - self.response_body=[] - - def resetParams(self): - self.response_status='200 Ok' - self.response_headers=[] - self.response_body=[] - - def add_response_body(self, string='', encoding='utf8'): - self.response_body+=[(string + "\n").encode(encoding)] - - def add_response_binary(self, data): - self.response_body+=[data] - - def add_response_header(self,list): - self.response_headers+=list - - def set_response_status(self,status): - self.response_status=status - - def write_response_headers(self, encoding='utf8'): - sys.stdout.buffer.write(b'Status: '+self.response_status.encode(encoding)+ b'\n') - for header in self.response_headers: - (a,b)=header - sys.stdout.buffer.write(a.encode(encoding)+b': '+b.encode(encoding) + b'\n') - sys.stdout.buffer.write(b'\n') - - def write_response(self): - for element in self.response_body: - sys.stdout.buffer.write(element + b'\n') - - def document_header(self,page_data): - self.add_response_header([self.template.response_header]) - self.add_response_body(self.template.document_header%dictmerge(self.site_data, page_data, {'style':self.template.document_style})) - - def document_footer(self,page_data): - self.add_response_body(self.template.document_footer%dictmerge(self.site_data,page_data)) - - def page_top(self, page_data): - data=dictmerge(self.site_data,page_data) - self.add_response_body(self.template.page_top_start%data) - self.add_response_body(self.template.page_top_linkstart%data) - self.add_response_body(self.template.page_top_linkself%data) - self.add_response_body(self.template.page_top_linksearch%data) - self.add_response_body(self.template.page_top_finish%data) - - def page_bottom(self, page_data): - data=dictmerge(self.site_data,page_data) - self.add_response_body(self.template.page_bottom_start%data) - self.add_response_body(self.template.page_bottom_info%data) - self.add_response_body(self.template.page_bottom_finish%data) - - def page_title(self, page_data): - data=dictmerge(self.site_data,page_data) - self.add_response_body(self.template.page_title_start%data) - self.add_response_body(self.template.page_title_info%data) - self.add_response_body(self.template.page_title_finish%data) - - def main_menu(self,USER,DBINFO): - if self.cfg.ALPHA: am='30' - else: am='' - self.add_response_body(self.template.document_mainmenu_std%dictmerge(self.site_data,{'cat_num':DBINFO[2][1],'book_num':DBINFO[0][1],'author_num':DBINFO[1][1],'genre_num':DBINFO[3][1],'series_num':DBINFO[4][1],'alphabet_id':am})) - if self.cfg.NEW_PERIOD!=0: - self.add_response_body(self.template.document_mainmenu_new%dictmerge(self.site_data,{'new_period':self.cfg.NEW_PERIOD})) - if self.cfg.BOOK_SHELF and USER!=None: - self.add_response_body(self.template.document_mainmenu_shelf%dictmerge(self.site_data,{'user':USER,'shelf_book_num':DBINFO[5][1]})) - - def new_menu(self,NEWINFO): - if self.cfg.ALPHA: am='30' - else: am='' - self.add_response_body(self.template.document_newmenu%dictmerge(self.site_data,{'new_period':self.cfg.NEW_PERIOD,'newbook_num':NEWINFO[0][1],'alphabet_id':am})) - - def authors_submenu(self,author_id): - self.add_response_body(self.template.document_authors_submenu%dictmerge(self.site_data,{'author_id':author_id})) - - def get_authors(self,tupleAUTHORS): - authors="" - authors_link="" - for (author_id,first_name,last_name) in tupleAUTHORS: - authors_link+=self.template.agregate_authors_link%dictmerge(self.site_data,{'author_id':author_id,'last_name':websym(last_name,True),'first_name':websym(first_name,True)}) - authors+=self.template.agregate_authors%dictmerge(self.site_data,{'author_id':author_id,'last_name':websym(last_name,True),'first_name':websym(first_name,True)}) - return (authors, authors_link) - - def get_genres(self,tupleGENRES): - genres="" - genres_link="" - for (genre_id,section,genre) in tupleGENRES: - genres_link+=self.template.agregate_genres_link%dictmerge(self.site_data,{'genre_id':genre_id,'genre':websym(genre)}) - genres+=self.template.agregate_genres%dictmerge(self.site_data,{'genre_id':genre_id,'genre':websym(genre)}) - return (genres, genres_link) - - def get_series(self,tupleSERIES): - series="" - series_link="" - for (ser_id,ser,ser_no) in tupleSERIES: - series_link+=self.template.agregate_series_link%dictmerge(self.site_data,{'ser_id':ser_id,'ser':websym(ser),'ser_no':ser_no}) - series+=self.template.agregate_series%dictmerge(self.site_data,{'ser_id':ser_id,'ser':websym(ser),'ser_no':ser_no}) - return (series, series_link) - - def entry_navigation(self,nav_data): - data=dictmerge(self.site_data,nav_data) - self.add_response_body(self.template.document_entry_nav_start%data) - self.add_response_body(self.template.document_entry_nav_title%data) - self.add_response_body(self.template.document_entry_nav_link%data) - self.add_response_body(self.template.document_entry_nav_info%data) - self.add_response_body(self.template.document_entry_nav_finish%data) - - def entry_acq_link_book(self,acq_data): - data=dictmerge(self.site_data,acq_data) - if data['e_date']==None: - data['e_date']=datetime.datetime(2001,9,9,0,0,0) - self.add_response_body(self.template.document_entry_acq_book_title%data) - self.add_response_body(self.template.document_entry_acq_book_link_alternate%data) - data['id']=91 - self.add_response_body(self.template.document_entry_acq_book_link%data) - if data['format'].lower()!='epub': - data['id']=92 - data['format']=data['format']+'+zip' - self.add_response_body(self.template.document_entry_acq_book_link%data) - if acq_data['format'].lower()=='fb2' and self.cfg.FB2TOEPUB: - data['id']=93 - data['format']='epub' - self.add_response_body(self.template.document_entry_acq_book_link%data) - if acq_data['format'].lower()=='fb2' and self.cfg.FB2TOMOBI: - data['id']=94 - data['format']='mobi' - self.add_response_body(self.template.document_entry_acq_book_link%data) - - def entry_acq_info_book(self,acq_data): - data=dictmerge(self.site_data,acq_data) - self.add_response_body(self.template.document_entry_acq_infobook_start%data) - if acq_data['e_title']!='': - self.add_response_body(self.template.document_entry_acq_infobook_title%data) - if acq_data['authors']!='': - self.add_response_body(self.template.document_entry_acq_infobook_authors%data) - if acq_data['genres']!='': - self.add_response_body(self.template.document_entry_acq_infobook_genres%data) - if acq_data['series']!='': - self.add_response_body(self.template.document_entry_acq_infobook_series%data) - if acq_data['filename']!='': - self.add_response_body(self.template.document_entry_acq_infobook_filename%data) - if acq_data['filesize']>0: - self.add_response_body(self.template.document_entry_acq_infobook_filesize%data) - if acq_data['docdate']!='': - self.add_response_body(self.template.document_entry_acq_infobook_docdate%data) - if acq_data['annotation']!='': - self.add_response_body(self.template.document_entry_acq_infobook_annotation%data) - self.add_response_body(self.template.document_entry_acq_infobook_userdata%data) - self.add_response_body(self.template.document_entry_acq_infobook_finish%data) - - def entry_acq_rel_doubles(self,acq_data): - data=dictmerge(self.site_data,acq_data) - if data['dcount']>0: - self.add_response_body(self.template.document_entry_acq_rel_doubles%acq_data) - - def entry_acquisition(self,acq_data): - data=dictmerge(self.site_data,acq_data) - self.add_response_body(self.template.document_entry_acq_start%data) - self.add_response_body(self.template.document_entry_acq_link_start%data) - self.entry_acq_link_book(data) - self.add_response_body(self.template.document_entry_acq_link_finish%data) - self.add_response_body(self.template.document_entry_acq_info_start%data) - self.add_response_body(self.template.document_entry_acq_info_cover%data) - self.entry_acq_info_book(data) - self.add_response_body(self.template.document_entry_acq_rel_start%data) - self.entry_acq_rel_doubles(data) - self.add_response_body(self.template.document_entry_acq_rel_authors%data) - self.add_response_body(self.template.document_entry_acq_rel_genres%data) - self.add_response_body(self.template.document_entry_acq_rel_finish%data) - self.add_response_body(self.template.document_entry_acq_info_finish%data) - self.add_response_body(self.template.document_entry_acq_finish%data) - - def page_control(self, page_data): - self.add_response_body(self.template.document_page_control_start%dictmerge(self.site_data,page_data)) - if page_data['page_prev']>=0: - self.add_response_body(self.template.document_page_control_prev%dictmerge(self.site_data,page_data)) - if page_data['page_next']>=0: - self.add_response_body(self.template.document_page_control_next%dictmerge(self.site_data,page_data)) - self.add_response_body(self.template.document_page_control_finish%dictmerge(self.site_data,page_data)) - - def alphabet_menu(self,iid_value,nl): - self.add_response_body(self.template.document_alphabet_menu%dictmerge(self.site_data,{'iid':iid_value,'nl':nl})) - - def opensearch(self): - self.add_response_header([self.template.response_header]) - self.add_response_body(self.template.opensearch%self.site_data) - - def opensearch_forms(self, page_data): - self.add_response_body(self.template.opensearch_forms%dictmerge(self.site_data,page_data)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..d510bdfb6b6e6f27190efd29a3a2bebfe5b5080a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Django>=1.8 +Pillow>=2.9.0 +apscheduler>=3.3.0 \ No newline at end of file diff --git a/sopds/__init__.py b/sopds/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/sopds/__pycache__/__init__.cpython-35.pyc b/sopds/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c564d270648ec4177e8204efc6c1d0aea3f52f3 Binary files /dev/null and b/sopds/__pycache__/__init__.cpython-35.pyc differ diff --git a/sopds/__pycache__/settings.cpython-35.pyc b/sopds/__pycache__/settings.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df7202747772a97e9d78bc6251a8c175884c9e63 Binary files /dev/null and b/sopds/__pycache__/settings.cpython-35.pyc differ diff --git a/sopds/__pycache__/urls.cpython-35.pyc b/sopds/__pycache__/urls.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14ecb61236708e72c5f5b8b881bcb502325011fb Binary files /dev/null and b/sopds/__pycache__/urls.cpython-35.pyc differ diff --git a/sopds/__pycache__/wsgi.cpython-35.pyc b/sopds/__pycache__/wsgi.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05d02a21e34268d7fc269662c4e1d6ea3d2fab7a Binary files /dev/null and b/sopds/__pycache__/wsgi.cpython-35.pyc differ diff --git a/sopds/settings.py b/sopds/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..6a711e72f41228e13c14f4aac59cdfb63001ae2a --- /dev/null +++ b/sopds/settings.py @@ -0,0 +1,149 @@ +""" +Django settings for sopds project. + +Generated by 'django-admin startproject' using Django 1.9.2. + +For more information on this file, see +https://docs.djangoproject.com/en/1.9/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.9/ref/settings/ +""" + +import os +import sys + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'm4l1c#nq6*zs!c3ri4dg4(54_7bvrl5uintni6p20tijlaxv!x' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +# Конфигурация для ведения разработки на разных хостах +# убрать при окончании разработки +import socket +HOSTNAME=socket.gethostname().upper() + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'opds_catalog', + 'sopds_web_backend', +] + +MIDDLEWARE_CLASSES = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'opds_catalog.opds_middleware.BasicAuthMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'sopds.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')] + , + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + 'sopds_web_backend.views.sopds_processor', + ], + }, + }, +] + +WSGI_APPLICATION = 'sopds.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.9/ref/settings/#databases + +#DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.mysql', +# 'NAME': 'sopds', +# 'HOST': 'localhost', +# 'USER': 'sopds', +# 'PASSWORD' : 'sopds' +# } +#} + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + +# Password validation +# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.9/topics/i18n/ + +LANGUAGE_CODE = 'ru-RU' +#LANGUAGE_CODE = 'en-US' + +TIME_ZONE = 'Europe/Moscow' +USE_I18N = True +USE_L10N = True +USE_TZ = True + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.9/howto/static-files/ +STATIC_URL = '/static/' +STATIC_ROOT = 'static' + +SOPDS_ROOT_LIB = 'Z:\\КНИГИ\\TEST\\' +#SOPDS_ROOT_LIB = '/mnt/SATA1TB-1/КНИГИ/BOOKS/' +SOPDS_AUTH = True +SOPDS_SCAN_SHED_MIN ='0' +SOPDS_SCAN_SHED_HOUR ='0,12' + +#Конвертеры EPUB и MOBI +#SOPDS_FB2TOEPUB = os.path.join(BASE_DIR,'convert/fb2toepub/unix_dist/fb2toepub') +#SOPDS_FB2TOEPUB = os.path.join(BASE_DIR,'convert/fb2conv/fb2epub') +#SOPDS_FB2TOMOBI = os.path.join(BASE_DIR,'convert/fb2conv/fb2mobi') +SOPDS_FB2TOEPUB = os.path.join(BASE_DIR, 'convert\\fb2epub\\fb2epub.cmd' if sys.platform =='win32' else 'convert/fb2epub/fb2epub' ) + diff --git a/sopds/urls.py b/sopds/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..18166ac1d469ebb892e9288576f94adf4a177d63 --- /dev/null +++ b/sopds/urls.py @@ -0,0 +1,26 @@ +"""sopds URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.9/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url, include +from django.contrib import admin +from django.contrib.auth.views import logout + +urlpatterns = [ + url(r'^opds/', include('opds_catalog.urls', namespace='opds', app_name='opds_catalog')), + url(r'^web/', include('sopds_web_backend.urls', namespace='web', app_name='opds_web_backend')), + url(r'^admin/', admin.site.urls), + url(r'^logout/$', logout, {'next_page':'/web/'},name='logout'), + url(r'^', include('sopds_web_backend.urls', namespace='web', app_name='opds_web_backend')), +] diff --git a/sopds/wsgi.py b/sopds/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..7b5f2c2cfbb52ca965c40864809fd1c99c3e45c3 --- /dev/null +++ b/sopds/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for sopds project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sopds.settings") + +application = get_wsgi_application() diff --git a/sopds_web_backend/__init__.py b/sopds_web_backend/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/sopds_web_backend/__pycache__/__init__.cpython-35.pyc b/sopds_web_backend/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12d702eeab449880e0a6e3623c49dea8fa9ab763 Binary files /dev/null and b/sopds_web_backend/__pycache__/__init__.cpython-35.pyc differ diff --git a/sopds_web_backend/__pycache__/admin.cpython-35.pyc b/sopds_web_backend/__pycache__/admin.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1a0c0e59e53120300fdf9c668a3bda1eb264194 Binary files /dev/null and b/sopds_web_backend/__pycache__/admin.cpython-35.pyc differ diff --git a/sopds_web_backend/__pycache__/models.cpython-35.pyc b/sopds_web_backend/__pycache__/models.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1f4f669d62f1ad04d01e673c413942a22006177 Binary files /dev/null and b/sopds_web_backend/__pycache__/models.cpython-35.pyc differ diff --git a/sopds_web_backend/__pycache__/settings.cpython-35.pyc b/sopds_web_backend/__pycache__/settings.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b423b7a4df6f44845242b6f4d5cd5b2432fa1f2 Binary files /dev/null and b/sopds_web_backend/__pycache__/settings.cpython-35.pyc differ diff --git a/sopds_web_backend/__pycache__/urls.cpython-35.pyc b/sopds_web_backend/__pycache__/urls.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2cb0add4c791414cb286c3aa10b4115c2216affb Binary files /dev/null and b/sopds_web_backend/__pycache__/urls.cpython-35.pyc differ diff --git a/sopds_web_backend/__pycache__/views.cpython-35.pyc b/sopds_web_backend/__pycache__/views.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4e17c69d32c4d7e4ffdedcf572d17aec3f03c12 Binary files /dev/null and b/sopds_web_backend/__pycache__/views.cpython-35.pyc differ diff --git a/sopds_web_backend/admin.py b/sopds_web_backend/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..694323fa4c8382f9effc636c7062ef168bb62da2 --- /dev/null +++ b/sopds_web_backend/admin.py @@ -0,0 +1 @@ +from django.contrib import admin diff --git a/sopds_web_backend/apps.py b/sopds_web_backend/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..168c581023b8d051bcd379c3d0ce5eaa13f44bd1 --- /dev/null +++ b/sopds_web_backend/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class SopdsWebBackendConfig(AppConfig): + name = 'sopds_web_backend' diff --git a/sopds_web_backend/locale/ru/LC_MESSAGES/django.mo b/sopds_web_backend/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..134072baf01c0d169d551f64777a5870aa72cb8a Binary files /dev/null and b/sopds_web_backend/locale/ru/LC_MESSAGES/django.mo differ diff --git a/sopds_web_backend/locale/ru/LC_MESSAGES/django.po b/sopds_web_backend/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..fd342d27d0615ce6c2b5034484b1c177161d8461 --- /dev/null +++ b/sopds_web_backend/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,237 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-11-07 00:41+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%" +"100>=11 && n%100<=14)? 2 : 3);\n" + +#: .\sopds_web_backend\templates\sopds_authors.html:8 +#, python-format +msgid "Total: %(a_book_count)s books." +msgstr "Всего: %(a_book_count)s книг." + +#: .\sopds_web_backend\templates\sopds_authors.html:17 +#: .\sopds_web_backend\templates\sopds_books.html:55 +#: .\sopds_web_backend\templates\sopds_catalogs.html:37 +#: .\sopds_web_backend\templates\sopds_series.html:17 +msgid "Previous page" +msgstr "Назад" + +#: .\sopds_web_backend\templates\sopds_authors.html:32 +#: .\sopds_web_backend\templates\sopds_books.html:70 +#: .\sopds_web_backend\templates\sopds_catalogs.html:52 +#: .\sopds_web_backend\templates\sopds_series.html:32 +msgid "Next page" +msgstr "Вперед" + +#: .\sopds_web_backend\templates\sopds_books.html:8 +msgid "Download:" +msgstr "Скачать:" + +#: .\sopds_web_backend\templates\sopds_books.html:25 +msgid "Book title:" +msgstr "Название книги:" + +#: .\sopds_web_backend\templates\sopds_books.html:27 +msgid "Authors:" +msgstr "Авторы:" + +#: .\sopds_web_backend\templates\sopds_books.html:30 +#: .\sopds_web_backend\templates\sopds_menu.html:9 +#: .\sopds_web_backend\templates\sopds_menu.html:31 +#: .\sopds_web_backend\views.py:492 .\sopds_web_backend\views.py:496 +msgid "Genres" +msgstr "Жанры" + +#: .\sopds_web_backend\templates\sopds_books.html:33 +#: .\sopds_web_backend\templates\sopds_logo.html:29 +#: .\sopds_web_backend\templates\sopds_menu.html:10 +#: .\sopds_web_backend\templates\sopds_menu.html:33 +#: .\sopds_web_backend\views.py:251 .\sopds_web_backend\views.py:478 +msgid "Series" +msgstr "Серии" + +#: .\sopds_web_backend\templates\sopds_books.html:35 +msgid "File:" +msgstr "Файл:" + +#: .\sopds_web_backend\templates\sopds_books.html:36 +msgid "File size:" +msgstr "Размер файла:" + +#: .\sopds_web_backend\templates\sopds_books.html:37 +msgid "Changes date:" +msgstr "Дата правки:" + +#: .\sopds_web_backend\templates\sopds_books.html:39 +msgid "Doubles for book:" +msgstr "Дубликаты книги:" + +#: .\sopds_web_backend\templates\sopds_breadcrumbs.html:3 +msgid "You are here:" +msgstr "Вы здесь:" + +#: .\sopds_web_backend\templates\sopds_footer.html:5 +msgid "BOOKSHELF" +msgstr "КНИЖНАЯ ПОЛКА" + +#: .\sopds_web_backend\templates\sopds_footer.html:18 +msgid "STATISTICS" +msgstr "СТАТИСТИКА" + +#: .\sopds_web_backend\templates\sopds_footer.html:20 +msgid "This сatalog contains:" +msgstr "Этот каталог содержит:" + +#: .\sopds_web_backend\templates\sopds_footer.html:21 +msgid "books," +msgstr "книг," + +#: .\sopds_web_backend\templates\sopds_footer.html:22 +msgid "authors," +msgstr "авторов," + +#: .\sopds_web_backend\templates\sopds_footer.html:23 +msgid "genres and" +msgstr "жанров и" + +#: .\sopds_web_backend\templates\sopds_footer.html:24 +msgid "series." +msgstr "серий." + +#: .\sopds_web_backend\templates\sopds_footer.html:27 +msgid "Last collection scan date:" +msgstr "Дата последнего сканирования:" + +#: .\sopds_web_backend\templates\sopds_footer.html:33 +msgid "RANDOM BOOK" +msgstr "СЛУЧАЙНАЯ КНИГА" + +#: .\sopds_web_backend\templates\sopds_logo.html:14 +#: .\sopds_web_backend\views.py:251 .\sopds_web_backend\views.py:308 +msgid "Search" +msgstr "Найти" + +#: .\sopds_web_backend\templates\sopds_logo.html:26 +msgid "Choose Search Type:" +msgstr "Выберите тип поиска:" + +#: .\sopds_web_backend\templates\sopds_logo.html:27 +msgid "Title" +msgstr "Название" + +#: .\sopds_web_backend\templates\sopds_logo.html:28 +msgid "Author" +msgstr "Автор" + +#: .\sopds_web_backend\templates\sopds_menu.html:6 +#: .\sopds_web_backend\templates\sopds_menu.html:16 +#: .\sopds_web_backend\views.py:378 +msgid "Catalogs" +msgstr "Каталоги" + +#: .\sopds_web_backend\templates\sopds_menu.html:7 +#: .\sopds_web_backend\templates\sopds_menu.html:17 +#: .\sopds_web_backend\views.py:73 .\sopds_web_backend\views.py:77 +#: .\sopds_web_backend\views.py:88 .\sopds_web_backend\views.py:99 +#: .\sopds_web_backend\views.py:107 .\sopds_web_backend\views.py:110 +#: .\sopds_web_backend\views.py:119 .\sopds_web_backend\views.py:123 +#: .\sopds_web_backend\views.py:131 .\sopds_web_backend\views.py:141 +#: .\sopds_web_backend\views.py:412 +msgid "Books" +msgstr "Книги" + +#: .\sopds_web_backend\templates\sopds_menu.html:8 +#: .\sopds_web_backend\templates\sopds_menu.html:24 +#: .\sopds_web_backend\views.py:308 .\sopds_web_backend\views.py:445 +msgid "Authors" +msgstr "Авторы" + +#: .\sopds_web_backend\templates\sopds_selectauthor.html:15 +#, python-format +msgid "Total: %(chars_cnt)s authors." +msgstr "Всего: %(chars_cnt)s авторов." + +#: .\sopds_web_backend\templates\sopds_selectbook.html:15 +#, python-format +msgid "Total: %(chars_cnt)s books." +msgstr "Всего: %(chars_cnt)s книг." + +#: .\sopds_web_backend\templates\sopds_selectgenres.html:15 +#, python-format +msgid "Total: %(g_num_book)s books." +msgstr "Всего: %(g_num_book)s книг." + +#: .\sopds_web_backend\templates\sopds_selectseries.html:15 +#, python-format +msgid "Total: %(chars_cnt)s series." +msgstr "Всего: %(chars_cnt)s серий." + +#: .\sopds_web_backend\templates\sopds_series.html:8 +#, python-format +msgid "Total: %(s_book_count)s books." +msgstr "Всего: %(s_book_count)s книг." + +#: .\sopds_web_backend\templates\sopds_top.html:19 +msgid "Logout" +msgstr "Выход" + +#: .\sopds_web_backend\templates\sopds_top.html:21 +msgid "Login" +msgstr "Вход" + +#: .\sopds_web_backend\templates\sopds_top.html:24 +msgid "Settings" +msgstr "Настройки" + +#: .\sopds_web_backend\views.py:73 .\sopds_web_backend\views.py:77 +msgid "Search by title" +msgstr "Поиск по наименованию" + +#: .\sopds_web_backend\views.py:88 +msgid "Search by author" +msgstr "Поиск по автору" + +#: .\sopds_web_backend\views.py:99 +msgid "Search by series" +msgstr "Поиск по серии" + +#: .\sopds_web_backend\views.py:107 .\sopds_web_backend\views.py:110 +msgid "Search by genre" +msgstr "Поиск по жанру" + +#: .\sopds_web_backend\views.py:119 .\sopds_web_backend\views.py:123 +msgid "Bookshelf" +msgstr "Книжная полка" + +#: .\sopds_web_backend\views.py:131 +msgid "Doubles for book" +msgstr "Дубликаты книги" + +#: .\sopds_web_backend\views.py:377 +msgid "ROOT" +msgstr "НАЧАЛО" + +#: .\sopds_web_backend\views.py:412 .\sopds_web_backend\views.py:445 +#: .\sopds_web_backend\views.py:478 .\sopds_web_backend\views.py:492 +#: .\sopds_web_backend\views.py:496 +msgid "Select" +msgstr "Выбор" + +#: .\sopds_web_backend\views.py:506 +msgid "HOME" +msgstr "ГЛАВНАЯ" diff --git a/sopds_web_backend/migrations/__init__.py b/sopds_web_backend/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/sopds_web_backend/migrations/__pycache__/__init__.cpython-35.pyc b/sopds_web_backend/migrations/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3349a12f19f6adb1fa330fdd81bfb8f69ef5efe6 Binary files /dev/null and b/sopds_web_backend/migrations/__pycache__/__init__.cpython-35.pyc differ diff --git a/sopds_web_backend/models.py b/sopds_web_backend/models.py new file mode 100644 index 0000000000000000000000000000000000000000..71a836239075aa6e6e4ecb700e9c42c95c022d91 --- /dev/null +++ b/sopds_web_backend/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/sopds_web_backend/settings.py b/sopds_web_backend/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..dc3a1a56ca41d5d32b5eef60d0c11ea134de2cc0 --- /dev/null +++ b/sopds_web_backend/settings.py @@ -0,0 +1 @@ +HALF_PAGES_LINKS = 3 \ No newline at end of file diff --git a/sopds_web_backend/static/css/foundation-flex.css b/sopds_web_backend/static/css/foundation-flex.css new file mode 100644 index 0000000000000000000000000000000000000000..12ca1435bae88fcf3efd71a570af65c10d748c86 --- /dev/null +++ b/sopds_web_backend/static/css/foundation-flex.css @@ -0,0 +1,3823 @@ +@charset "UTF-8"; +/** + * Foundation for Sites by ZURB + * Version 6.2.4 + * foundation.zurb.com + * Licensed under MIT Open Source + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS and IE text size adjust after device orientation change, + * without disabling user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability of focused elements when they are also in an + * active/hover state. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: not-allowed; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome. + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -webkit-box-sizing: content-box; + box-sizing: content-box; + /* 2 */ } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + * [NOTE] We don't enable this ruleset in Foundation, because we want the
element to have plain styling. + */ +/* fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; + } */ +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +.foundation-mq { + font-family: "small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"; } + +html { + font-size: 100%; + -webkit-box-sizing: border-box; + box-sizing: border-box; } + +*, +*::before, +*::after { + -webkit-box-sizing: inherit; + box-sizing: inherit; } + +body { + padding: 0; + margin: 0; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + line-height: 1.5; + color: #0a0a0a; + background: #fefefe; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + +img { + max-width: 100%; + height: auto; + -ms-interpolation-mode: bicubic; + display: inline-block; + vertical-align: middle; } + +textarea { + height: auto; + min-height: 50px; + border-radius: 0; } + +select { + width: 100%; + border-radius: 0; } + +#map_canvas img, +#map_canvas embed, +#map_canvas object, +.map_canvas img, +.map_canvas embed, +.map_canvas object, +.mqa-display img, +.mqa-display embed, +.mqa-display object { + max-width: none !important; } + +button { + -webkit-appearance: none; + -moz-appearance: none; + background: transparent; + padding: 0; + border: 0; + border-radius: 0; + line-height: 1; } + [data-whatinput='mouse'] button { + outline: 0; } + +.is-visible { + display: block !important; } + +.is-hidden { + display: none !important; } + +.row { + max-width: 75rem; + margin-left: auto; + margin-right: auto; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-flow: row wrap; + flex-flow: row wrap; } + .row .row { + margin-left: -0.625rem; + margin-right: -0.625rem; } + @media screen and (min-width: 40em) { + .row .row { + margin-left: -0.9375rem; + margin-right: -0.9375rem; } } + .row.expanded { + max-width: none; } + .row.collapse > .column, .row.collapse > .columns { + padding-left: 0; + padding-right: 0; } + .row.is-collapse-child, + .row.collapse > .column > .row, + .row.collapse > .columns > .row { + margin-left: 0; + margin-right: 0; } + +.column, .columns { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; + padding-left: 0.625rem; + padding-right: 0.625rem; + min-width: initial; } + @media screen and (min-width: 40em) { + .column, .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } } + +.column.row.row, .row.row.columns { + float: none; + display: block; } + +.row .column.row.row, .row .row.row.columns { + padding-left: 0; + padding-right: 0; + margin-left: 0; + margin-right: 0; } + +.small-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.33333%; + flex: 0 0 8.33333%; + max-width: 8.33333%; } + +.small-offset-0 { + margin-left: 0%; } + +.small-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.66667%; + flex: 0 0 16.66667%; + max-width: 16.66667%; } + +.small-offset-1 { + margin-left: 8.33333%; } + +.small-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } + +.small-offset-2 { + margin-left: 16.66667%; } + +.small-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.33333%; + flex: 0 0 33.33333%; + max-width: 33.33333%; } + +.small-offset-3 { + margin-left: 25%; } + +.small-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.66667%; + flex: 0 0 41.66667%; + max-width: 41.66667%; } + +.small-offset-4 { + margin-left: 33.33333%; } + +.small-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; } + +.small-offset-5 { + margin-left: 41.66667%; } + +.small-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.33333%; + flex: 0 0 58.33333%; + max-width: 58.33333%; } + +.small-offset-6 { + margin-left: 50%; } + +.small-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.66667%; + flex: 0 0 66.66667%; + max-width: 66.66667%; } + +.small-offset-7 { + margin-left: 58.33333%; } + +.small-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; } + +.small-offset-8 { + margin-left: 66.66667%; } + +.small-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.33333%; + flex: 0 0 83.33333%; + max-width: 83.33333%; } + +.small-offset-9 { + margin-left: 75%; } + +.small-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.66667%; + flex: 0 0 91.66667%; + max-width: 91.66667%; } + +.small-offset-10 { + margin-left: 83.33333%; } + +.small-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + +.small-offset-11 { + margin-left: 91.66667%; } + +.small-order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + +.small-order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; } + +.small-order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; } + +.small-order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; } + +.small-order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; } + +.small-order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; } + +.small-up-1 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-1 > .column, .small-up-1 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + +.small-up-2 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-2 > .column, .small-up-2 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; } + +.small-up-3 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-3 > .column, .small-up-3 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.33333%; + flex: 0 0 33.33333%; + max-width: 33.33333%; } + +.small-up-4 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-4 > .column, .small-up-4 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } + +.small-up-5 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-5 > .column, .small-up-5 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; } + +.small-up-6 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-6 > .column, .small-up-6 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.66667%; + flex: 0 0 16.66667%; + max-width: 16.66667%; } + +.small-up-7 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-7 > .column, .small-up-7 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 14.28571%; + flex: 0 0 14.28571%; + max-width: 14.28571%; } + +.small-up-8 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .small-up-8 > .column, .small-up-8 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 12.5%; + flex: 0 0 12.5%; + max-width: 12.5%; } + +.small-collapse > .column, .small-collapse > .columns { + padding-left: 0; + padding-right: 0; } + +.small-uncollapse > .column, .small-uncollapse > .columns { + padding-left: 0.625rem; + padding-right: 0.625rem; } + +@media screen and (min-width: 40em) { + .medium-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.33333%; + flex: 0 0 8.33333%; + max-width: 8.33333%; } + .medium-offset-0 { + margin-left: 0%; } + .medium-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.66667%; + flex: 0 0 16.66667%; + max-width: 16.66667%; } + .medium-offset-1 { + margin-left: 8.33333%; } + .medium-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } + .medium-offset-2 { + margin-left: 16.66667%; } + .medium-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.33333%; + flex: 0 0 33.33333%; + max-width: 33.33333%; } + .medium-offset-3 { + margin-left: 25%; } + .medium-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.66667%; + flex: 0 0 41.66667%; + max-width: 41.66667%; } + .medium-offset-4 { + margin-left: 33.33333%; } + .medium-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; } + .medium-offset-5 { + margin-left: 41.66667%; } + .medium-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.33333%; + flex: 0 0 58.33333%; + max-width: 58.33333%; } + .medium-offset-6 { + margin-left: 50%; } + .medium-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.66667%; + flex: 0 0 66.66667%; + max-width: 66.66667%; } + .medium-offset-7 { + margin-left: 58.33333%; } + .medium-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; } + .medium-offset-8 { + margin-left: 66.66667%; } + .medium-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.33333%; + flex: 0 0 83.33333%; + max-width: 83.33333%; } + .medium-offset-9 { + margin-left: 75%; } + .medium-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.66667%; + flex: 0 0 91.66667%; + max-width: 91.66667%; } + .medium-offset-10 { + margin-left: 83.33333%; } + .medium-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + .medium-offset-11 { + margin-left: 91.66667%; } + .medium-order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .medium-order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; } + .medium-order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; } + .medium-order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; } + .medium-order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; } + .medium-order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; } + .medium-up-1 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-1 > .column, .medium-up-1 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + .medium-up-2 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-2 > .column, .medium-up-2 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; } + .medium-up-3 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-3 > .column, .medium-up-3 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.33333%; + flex: 0 0 33.33333%; + max-width: 33.33333%; } + .medium-up-4 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-4 > .column, .medium-up-4 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } + .medium-up-5 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-5 > .column, .medium-up-5 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; } + .medium-up-6 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-6 > .column, .medium-up-6 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.66667%; + flex: 0 0 16.66667%; + max-width: 16.66667%; } + .medium-up-7 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-7 > .column, .medium-up-7 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 14.28571%; + flex: 0 0 14.28571%; + max-width: 14.28571%; } + .medium-up-8 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .medium-up-8 > .column, .medium-up-8 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 12.5%; + flex: 0 0 12.5%; + max-width: 12.5%; } } + +@media screen and (min-width: 40em) and (min-width: 40em) { + .medium-expand { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } } + +.row.medium-unstack > .column, .row.medium-unstack > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; } + @media screen and (min-width: 40em) { + .row.medium-unstack > .column, .row.medium-unstack > .columns { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } } + +@media screen and (min-width: 40em) { + .medium-collapse > .column, .medium-collapse > .columns { + padding-left: 0; + padding-right: 0; } + .medium-uncollapse > .column, .medium-uncollapse > .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } } + +@media screen and (min-width: 64em) { + .large-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.33333%; + flex: 0 0 8.33333%; + max-width: 8.33333%; } + .large-offset-0 { + margin-left: 0%; } + .large-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.66667%; + flex: 0 0 16.66667%; + max-width: 16.66667%; } + .large-offset-1 { + margin-left: 8.33333%; } + .large-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } + .large-offset-2 { + margin-left: 16.66667%; } + .large-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.33333%; + flex: 0 0 33.33333%; + max-width: 33.33333%; } + .large-offset-3 { + margin-left: 25%; } + .large-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.66667%; + flex: 0 0 41.66667%; + max-width: 41.66667%; } + .large-offset-4 { + margin-left: 33.33333%; } + .large-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; } + .large-offset-5 { + margin-left: 41.66667%; } + .large-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.33333%; + flex: 0 0 58.33333%; + max-width: 58.33333%; } + .large-offset-6 { + margin-left: 50%; } + .large-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.66667%; + flex: 0 0 66.66667%; + max-width: 66.66667%; } + .large-offset-7 { + margin-left: 58.33333%; } + .large-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; } + .large-offset-8 { + margin-left: 66.66667%; } + .large-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.33333%; + flex: 0 0 83.33333%; + max-width: 83.33333%; } + .large-offset-9 { + margin-left: 75%; } + .large-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.66667%; + flex: 0 0 91.66667%; + max-width: 91.66667%; } + .large-offset-10 { + margin-left: 83.33333%; } + .large-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + .large-offset-11 { + margin-left: 91.66667%; } + .large-order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .large-order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; } + .large-order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; } + .large-order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; } + .large-order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; } + .large-order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; } + .large-up-1 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-1 > .column, .large-up-1 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + .large-up-2 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-2 > .column, .large-up-2 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; } + .large-up-3 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-3 > .column, .large-up-3 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.33333%; + flex: 0 0 33.33333%; + max-width: 33.33333%; } + .large-up-4 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-4 > .column, .large-up-4 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } + .large-up-5 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-5 > .column, .large-up-5 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; } + .large-up-6 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-6 > .column, .large-up-6 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.66667%; + flex: 0 0 16.66667%; + max-width: 16.66667%; } + .large-up-7 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-7 > .column, .large-up-7 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 14.28571%; + flex: 0 0 14.28571%; + max-width: 14.28571%; } + .large-up-8 { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .large-up-8 > .column, .large-up-8 > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 12.5%; + flex: 0 0 12.5%; + max-width: 12.5%; } } + +@media screen and (min-width: 64em) and (min-width: 64em) { + .large-expand { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } } + +.row.large-unstack > .column, .row.large-unstack > .columns { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; } + @media screen and (min-width: 64em) { + .row.large-unstack > .column, .row.large-unstack > .columns { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } } + +@media screen and (min-width: 64em) { + .large-collapse > .column, .large-collapse > .columns { + padding-left: 0; + padding-right: 0; } + .large-uncollapse > .column, .large-uncollapse > .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } } + +.shrink { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + max-width: 100%; } + +.column.align-top, .align-top.columns { + -ms-flex-item-align: start; + align-self: flex-start; } + +.column.align-bottom, .align-bottom.columns { + -ms-flex-item-align: end; + align-self: flex-end; } + +.column.align-middle, .align-middle.columns { + -ms-flex-item-align: center; + align-self: center; } + +.column.align-stretch, .align-stretch.columns { + -ms-flex-item-align: stretch; + align-self: stretch; } + +div, +dl, +dt, +dd, +ul, +ol, +li, +h1, +h2, +h3, +h4, +h5, +h6, +pre, +form, +p, +blockquote, +th, +td { + margin: 0; + padding: 0; } + +p { + font-size: inherit; + line-height: 1.6; + margin-bottom: 1rem; + text-rendering: optimizeLegibility; } + +em, +i { + font-style: italic; + line-height: inherit; } + +strong, +b { + font-weight: bold; + line-height: inherit; } + +small { + font-size: 80%; + line-height: inherit; } + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + font-style: normal; + color: inherit; + text-rendering: optimizeLegibility; + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.4; } + h1 small, + h2 small, + h3 small, + h4 small, + h5 small, + h6 small { + color: #cacaca; + line-height: 0; } + +h1 { + font-size: 1.5rem; } + +h2 { + font-size: 1.25rem; } + +h3 { + font-size: 1.1875rem; } + +h4 { + font-size: 1.125rem; } + +h5 { + font-size: 1.0625rem; } + +h6 { + font-size: 1rem; } + +@media screen and (min-width: 40em) { + h1 { + font-size: 3rem; } + h2 { + font-size: 2.5rem; } + h3 { + font-size: 1.9375rem; } + h4 { + font-size: 1.5625rem; } + h5 { + font-size: 1.25rem; } + h6 { + font-size: 1rem; } } + +a { + color: #2199e8; + text-decoration: none; + line-height: inherit; + cursor: pointer; } + a:hover, a:focus { + color: #1585cf; } + a img { + border: 0; } + +hr { + max-width: 75rem; + height: 0; + border-right: 0; + border-top: 0; + border-bottom: 1px solid #cacaca; + border-left: 0; + margin: 1.25rem auto; + clear: both; } + +ul, +ol, +dl { + line-height: 1.6; + margin-bottom: 1rem; + list-style-position: outside; } + +li { + font-size: inherit; } + +ul { + list-style-type: disc; + margin-left: 1.25rem; } + +ol { + margin-left: 1.25rem; } + +ul ul, ol ul, ul ol, ol ol { + margin-left: 1.25rem; + margin-bottom: 0; } + +dl { + margin-bottom: 1rem; } + dl dt { + margin-bottom: 0.3rem; + font-weight: bold; } + +blockquote { + margin: 0 0 1rem; + padding: 0.5625rem 1.25rem 0 1.1875rem; + border-left: 1px solid #cacaca; } + blockquote, blockquote p { + line-height: 1.6; + color: #8a8a8a; } + +cite { + display: block; + font-size: 0.8125rem; + color: #8a8a8a; } + cite:before { + content: '\2014 \0020'; } + +abbr { + color: #0a0a0a; + cursor: help; + border-bottom: 1px dotted #0a0a0a; } + +code { + font-family: Consolas, "Liberation Mono", Courier, monospace; + font-weight: normal; + color: #0a0a0a; + background-color: #e6e6e6; + border: 1px solid #cacaca; + padding: 0.125rem 0.3125rem 0.0625rem; } + +kbd { + padding: 0.125rem 0.25rem 0; + margin: 0; + background-color: #e6e6e6; + color: #0a0a0a; + font-family: Consolas, "Liberation Mono", Courier, monospace; } + +.subheader { + margin-top: 0.2rem; + margin-bottom: 0.5rem; + font-weight: normal; + line-height: 1.4; + color: #8a8a8a; } + +.lead { + font-size: 125%; + line-height: 1.6; } + +.stat { + font-size: 2.5rem; + line-height: 1; } + p + .stat { + margin-top: -1rem; } + +.no-bullet { + margin-left: 0; + list-style: none; } + +.text-left { + text-align: left; } + +.text-right { + text-align: right; } + +.text-center { + text-align: center; } + +.text-justify { + text-align: justify; } + +@media screen and (min-width: 40em) { + .medium-text-left { + text-align: left; } + .medium-text-right { + text-align: right; } + .medium-text-center { + text-align: center; } + .medium-text-justify { + text-align: justify; } } + +@media screen and (min-width: 64em) { + .large-text-left { + text-align: left; } + .large-text-right { + text-align: right; } + .large-text-center { + text-align: center; } + .large-text-justify { + text-align: justify; } } + +.show-for-print { + display: none !important; } + +@media print { + * { + background: transparent !important; + color: black !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; } + .show-for-print { + display: block !important; } + .hide-for-print { + display: none !important; } + table.show-for-print { + display: table !important; } + thead.show-for-print { + display: table-header-group !important; } + tbody.show-for-print { + display: table-row-group !important; } + tr.show-for-print { + display: table-row !important; } + td.show-for-print { + display: table-cell !important; } + th.show-for-print { + display: table-cell !important; } + a, + a:visited { + text-decoration: underline; } + a[href]:after { + content: " (" attr(href) ")"; } + .ir a:after, + a[href^='javascript:']:after, + a[href^='#']:after { + content: ''; } + abbr[title]:after { + content: " (" attr(title) ")"; } + pre, + blockquote { + border: 1px solid #8a8a8a; + page-break-inside: avoid; } + thead { + display: table-header-group; } + tr, + img { + page-break-inside: avoid; } + img { + max-width: 100% !important; } + @page { + margin: 0.5cm; } + p, + h2, + h3 { + orphans: 3; + widows: 3; } + h2, + h3 { + page-break-after: avoid; } } + +[type='text'], [type='password'], [type='date'], [type='datetime'], [type='datetime-local'], [type='month'], [type='week'], [type='email'], [type='number'], [type='search'], [type='tel'], [type='time'], [type='url'], [type='color'], +textarea { + display: block; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 2.4375rem; + padding: 0.5rem; + border: 1px solid #cacaca; + margin: 0 0 1rem; + font-family: inherit; + font-size: 1rem; + color: #0a0a0a; + background-color: #fefefe; + -webkit-box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + border-radius: 0; + -webkit-transition: -webkit-box-shadow 0.5s, border-color 0.25s ease-in-out; + transition: box-shadow 0.5s, border-color 0.25s ease-in-out; + -webkit-appearance: none; + -moz-appearance: none; } + [type='text']:focus, [type='password']:focus, [type='date']:focus, [type='datetime']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='week']:focus, [type='email']:focus, [type='number']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='url']:focus, [type='color']:focus, + textarea:focus { + border: 1px solid #8a8a8a; + background-color: #fefefe; + outline: none; + -webkit-box-shadow: 0 0 5px #cacaca; + box-shadow: 0 0 5px #cacaca; + -webkit-transition: -webkit-box-shadow 0.5s, border-color 0.25s ease-in-out; + transition: box-shadow 0.5s, border-color 0.25s ease-in-out; } + +textarea { + max-width: 100%; } + textarea[rows] { + height: auto; } + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #cacaca; } + +input::-moz-placeholder, +textarea::-moz-placeholder { + color: #cacaca; } + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #cacaca; } + +input::placeholder, +textarea::placeholder { + color: #cacaca; } + +input:disabled, input[readonly], +textarea:disabled, +textarea[readonly] { + background-color: #e6e6e6; + cursor: not-allowed; } + +[type='submit'], +[type='button'] { + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; } + +input[type='search'] { + -webkit-box-sizing: border-box; + box-sizing: border-box; } + +[type='file'], +[type='checkbox'], +[type='radio'] { + margin: 0 0 1rem; } + +[type='checkbox'] + label, +[type='radio'] + label { + display: inline-block; + margin-left: 0.5rem; + margin-right: 1rem; + margin-bottom: 0; + vertical-align: baseline; } + [type='checkbox'] + label[for], + [type='radio'] + label[for] { + cursor: pointer; } + +label > [type='checkbox'], +label > [type='radio'] { + margin-right: 0.5rem; } + +[type='file'] { + width: 100%; } + +label { + display: block; + margin: 0; + font-size: 0.875rem; + font-weight: normal; + line-height: 1.8; + color: #0a0a0a; } + label.middle { + margin: 0 0 1rem; + padding: 0.5625rem 0; } + +.help-text { + margin-top: -0.5rem; + font-size: 0.8125rem; + font-style: italic; + color: #0a0a0a; } + +.input-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + width: 100%; + margin-bottom: 1rem; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; } + .input-group > :first-child { + border-radius: 0 0 0 0; } + .input-group > :last-child > * { + border-radius: 0 0 0 0; } + +.input-group-label, .input-group-field, .input-group-button { + margin: 0; + white-space: nowrap; } + +.input-group-label { + text-align: center; + padding: 0 1rem; + background: #e6e6e6; + color: #0a0a0a; + border: 1px solid #cacaca; + white-space: nowrap; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .input-group-label:first-child { + border-right: 0; } + .input-group-label:last-child { + border-left: 0; } + +.input-group-field { + border-radius: 0; + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; + height: auto; } + +.input-group-button { + padding-top: 0; + padding-bottom: 0; + text-align: center; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; } + .input-group-button a, + .input-group-button input, + .input-group-button button { + margin: 0; } + +fieldset { + border: 0; + padding: 0; + margin: 0; } + +legend { + margin-bottom: 0.5rem; + max-width: 100%; } + +.fieldset { + border: 1px solid #cacaca; + padding: 1.25rem; + margin: 1.125rem 0; } + .fieldset legend { + background: #fefefe; + padding: 0 0.1875rem; + margin: 0; + margin-left: -0.1875rem; } + +select { + height: 2.4375rem; + padding: 0.5rem; + border: 1px solid #cacaca; + margin: 0 0 1rem; + font-size: 1rem; + font-family: inherit; + line-height: normal; + color: #0a0a0a; + background-color: #fefefe; + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + -webkit-background-size: 9px 6px; + background-size: 9px 6px; + background-position: right -1rem center; + -webkit-background-origin: content-box; + background-origin: content-box; + background-repeat: no-repeat; + padding-right: 1.5rem; } + @media screen and (min-width: 0\0) { + select { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg=="); } } + select:disabled { + background-color: #e6e6e6; + cursor: not-allowed; } + select::-ms-expand { + display: none; } + select[multiple] { + height: auto; + background-image: none; } + +.is-invalid-input:not(:focus) { + background-color: rgba(236, 88, 64, 0.1); + border-color: #ec5840; } + +.is-invalid-label { + color: #ec5840; } + +.form-error { + display: none; + margin-top: -0.5rem; + margin-bottom: 1rem; + font-size: 0.75rem; + font-weight: bold; + color: #ec5840; } + .form-error.is-visible { + display: block; } + +.button { + display: inline-block; + text-align: center; + line-height: 1; + cursor: pointer; + -webkit-appearance: none; + -webkit-transition: background-color 0.25s ease-out, color 0.25s ease-out; + transition: background-color 0.25s ease-out, color 0.25s ease-out; + vertical-align: middle; + border: 1px solid transparent; + border-radius: 0; + padding: 0.85em 1em; + margin: 0 0 1rem 0; + font-size: 0.9rem; + background-color: #2199e8; + color: #fefefe; } + [data-whatinput='mouse'] .button { + outline: 0; } + .button:hover, .button:focus { + background-color: #1583cc; + color: #fefefe; } + .button.tiny { + font-size: 0.6rem; } + .button.small { + font-size: 0.75rem; } + .button.large { + font-size: 1.25rem; } + .button.expanded { + display: block; + width: 100%; + margin-left: 0; + margin-right: 0; } + .button.primary { + background-color: #2199e8; + color: #fefefe; } + .button.primary:hover, .button.primary:focus { + background-color: #147cc0; + color: #fefefe; } + .button.secondary { + background-color: #777; + color: #fefefe; } + .button.secondary:hover, .button.secondary:focus { + background-color: #5f5f5f; + color: #fefefe; } + .button.success { + background-color: #3adb76; + color: #fefefe; } + .button.success:hover, .button.success:focus { + background-color: #22bb5b; + color: #fefefe; } + .button.warning { + background-color: #ffae00; + color: #fefefe; } + .button.warning:hover, .button.warning:focus { + background-color: #cc8b00; + color: #fefefe; } + .button.alert { + background-color: #ec5840; + color: #fefefe; } + .button.alert:hover, .button.alert:focus { + background-color: #da3116; + color: #fefefe; } + .button.hollow { + border: 1px solid #2199e8; + color: #2199e8; } + .button.hollow, .button.hollow:hover, .button.hollow:focus { + background-color: transparent; } + .button.hollow:hover, .button.hollow:focus { + border-color: #0c4d78; + color: #0c4d78; } + .button.hollow.primary { + border: 1px solid #2199e8; + color: #2199e8; } + .button.hollow.primary:hover, .button.hollow.primary:focus { + border-color: #0c4d78; + color: #0c4d78; } + .button.hollow.secondary { + border: 1px solid #777; + color: #777; } + .button.hollow.secondary:hover, .button.hollow.secondary:focus { + border-color: #3c3c3c; + color: #3c3c3c; } + .button.hollow.success { + border: 1px solid #3adb76; + color: #3adb76; } + .button.hollow.success:hover, .button.hollow.success:focus { + border-color: #157539; + color: #157539; } + .button.hollow.warning { + border: 1px solid #ffae00; + color: #ffae00; } + .button.hollow.warning:hover, .button.hollow.warning:focus { + border-color: #805700; + color: #805700; } + .button.hollow.alert { + border: 1px solid #ec5840; + color: #ec5840; } + .button.hollow.alert:hover, .button.hollow.alert:focus { + border-color: #881f0e; + color: #881f0e; } + .button.disabled, .button[disabled] { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus { + background-color: #2199e8; + color: #fefefe; } + .button.disabled.primary, .button[disabled].primary { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.primary:hover, .button.disabled.primary:focus, .button[disabled].primary:hover, .button[disabled].primary:focus { + background-color: #2199e8; + color: #fefefe; } + .button.disabled.secondary, .button[disabled].secondary { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus { + background-color: #777; + color: #fefefe; } + .button.disabled.success, .button[disabled].success { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus { + background-color: #3adb76; + color: #fefefe; } + .button.disabled.warning, .button[disabled].warning { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.warning:hover, .button.disabled.warning:focus, .button[disabled].warning:hover, .button[disabled].warning:focus { + background-color: #ffae00; + color: #fefefe; } + .button.disabled.alert, .button[disabled].alert { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus { + background-color: #ec5840; + color: #fefefe; } + .button.dropdown::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.4em; + border-color: #fefefe transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + position: relative; + top: 0.4em; + float: right; + margin-left: 1em; + display: inline-block; } + .button.arrow-only::after { + margin-left: 0; + float: none; + top: -0.1em; } + +.accordion { + list-style-type: none; + background: #fefefe; + margin-left: 0; } + +.accordion-item:first-child > :first-child { + border-radius: 0 0 0 0; } + +.accordion-item:last-child > :last-child { + border-radius: 0 0 0 0; } + +.accordion-title { + display: block; + padding: 1.25rem 1rem; + line-height: 1; + font-size: 0.75rem; + color: #2199e8; + position: relative; + border: 1px solid #e6e6e6; + border-bottom: 0; } + :last-child:not(.is-active) > .accordion-title { + border-radius: 0 0 0 0; + border-bottom: 1px solid #e6e6e6; } + .accordion-title:hover, .accordion-title:focus { + background-color: #e6e6e6; } + .accordion-title::before { + content: '+'; + position: absolute; + right: 1rem; + top: 50%; + margin-top: -0.5rem; } + .is-active > .accordion-title::before { + content: '–'; } + +.accordion-content { + padding: 1rem; + display: none; + border: 1px solid #e6e6e6; + border-bottom: 0; + background-color: #fefefe; + color: #0a0a0a; } + :last-child > .accordion-content:last-child { + border-bottom: 1px solid #e6e6e6; } + +.is-accordion-submenu-parent > a { + position: relative; } + .is-accordion-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + position: absolute; + top: 50%; + margin-top: -4px; + right: 1rem; } + +.is-accordion-submenu-parent[aria-expanded='true'] > a::after { + -webkit-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + -webkit-transform: scaleY(-1); + -ms-transform: scaleY(-1); + transform: scaleY(-1); } + +.badge { + display: inline-block; + padding: 0.3em; + min-width: 2.1em; + font-size: 0.6rem; + text-align: center; + border-radius: 50%; + background: #2199e8; + color: #fefefe; } + .badge.secondary { + background: #777; + color: #fefefe; } + .badge.success { + background: #3adb76; + color: #fefefe; } + .badge.warning { + background: #ffae00; + color: #fefefe; } + .badge.alert { + background: #ec5840; + color: #fefefe; } + +.breadcrumbs { + list-style: none; + margin: 0 0 1rem 0; } + .breadcrumbs::before, .breadcrumbs::after { + content: ' '; + display: table; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .breadcrumbs::after { + clear: both; } + .breadcrumbs li { + float: left; + color: #0a0a0a; + font-size: 0.6875rem; + cursor: default; + text-transform: uppercase; } + .breadcrumbs li:not(:last-child)::after { + color: #cacaca; + content: "/"; + margin: 0 0.75rem; + position: relative; + top: 1px; + opacity: 1; } + .breadcrumbs a { + color: #2199e8; } + .breadcrumbs a:hover { + text-decoration: underline; } + .breadcrumbs .disabled { + color: #cacaca; + cursor: not-allowed; } + +.button-group { + margin-bottom: 1rem; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; } + .button-group::before, .button-group::after { + content: ' '; + display: table; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .button-group::after { + clear: both; } + .button-group .button { + margin: 0; + margin-right: 1px; + margin-bottom: 1px; + font-size: 0.9rem; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; } + .button-group .button:last-child { + margin-right: 0; } + .button-group.tiny .button { + font-size: 0.6rem; } + .button-group.small .button { + font-size: 0.75rem; } + .button-group.large .button { + font-size: 1.25rem; } + .button-group.expanded .button { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } + .button-group.primary .button { + background-color: #2199e8; + color: #fefefe; } + .button-group.primary .button:hover, .button-group.primary .button:focus { + background-color: #147cc0; + color: #fefefe; } + .button-group.secondary .button { + background-color: #777; + color: #fefefe; } + .button-group.secondary .button:hover, .button-group.secondary .button:focus { + background-color: #5f5f5f; + color: #fefefe; } + .button-group.success .button { + background-color: #3adb76; + color: #fefefe; } + .button-group.success .button:hover, .button-group.success .button:focus { + background-color: #22bb5b; + color: #fefefe; } + .button-group.warning .button { + background-color: #ffae00; + color: #fefefe; } + .button-group.warning .button:hover, .button-group.warning .button:focus { + background-color: #cc8b00; + color: #fefefe; } + .button-group.alert .button { + background-color: #ec5840; + color: #fefefe; } + .button-group.alert .button:hover, .button-group.alert .button:focus { + background-color: #da3116; + color: #fefefe; } + .button-group.stacked, .button-group.stacked-for-small, .button-group.stacked-for-medium { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .button-group.stacked .button, .button-group.stacked-for-small .button, .button-group.stacked-for-medium .button { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; } + .button-group.stacked .button:last-child, .button-group.stacked-for-small .button:last-child, .button-group.stacked-for-medium .button:last-child { + margin-bottom: 0; } + @media screen and (min-width: 40em) { + .button-group.stacked-for-small .button { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; + margin-bottom: 0; } } + @media screen and (min-width: 64em) { + .button-group.stacked-for-medium .button { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; + margin-bottom: 0; } } + @media screen and (max-width: 39.9375em) { + .button-group.stacked-for-small.expanded { + display: block; } + .button-group.stacked-for-small.expanded .button { + display: block; + margin-right: 0; } } + +.callout { + margin: 0 0 1rem 0; + padding: 1rem; + border: 1px solid rgba(10, 10, 10, 0.25); + border-radius: 0; + position: relative; + color: #0a0a0a; + background-color: white; } + .callout > :first-child { + margin-top: 0; } + .callout > :last-child { + margin-bottom: 0; } + .callout.primary { + background-color: #def0fc; } + .callout.secondary { + background-color: #ebebeb; } + .callout.success { + background-color: #e1faea; } + .callout.warning { + background-color: #fff3d9; } + .callout.alert { + background-color: #fce6e2; } + .callout.small { + padding-top: 0.5rem; + padding-right: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.5rem; } + .callout.large { + padding-top: 3rem; + padding-right: 3rem; + padding-bottom: 3rem; + padding-left: 3rem; } + +.close-button { + position: absolute; + color: #8a8a8a; + right: 1rem; + top: 0.5rem; + font-size: 2em; + line-height: 1; + cursor: pointer; } + [data-whatinput='mouse'] .close-button { + outline: 0; } + .close-button:hover, .close-button:focus { + color: #0a0a0a; } + +.menu { + margin: 0; + list-style-type: none; + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; } + .menu > li { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; } + [data-whatinput='mouse'] .menu > li { + outline: 0; } + .menu > li > a { + display: block; + padding: 0.7rem 1rem; + line-height: 1; } + .menu input, + .menu a, + .menu button { + margin-bottom: 0; } + .menu > li > a { + display: -webkit-box; + display: -ms-flexbox; + display: flex; } + .menu > li > a { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; } + .menu > li > a img, + .menu > li > a i, + .menu > li > a svg { + margin-right: 0.25rem; } + .menu > li { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; } + .menu.vertical { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .menu.vertical > li { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + .menu.vertical > li > a { + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; } + @media screen and (min-width: 40em) { + .menu.medium-horizontal { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; } + .menu.medium-horizontal > li { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; } + .menu.medium-vertical { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .menu.medium-vertical > li { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + .menu.medium-vertical > li > a { + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; } } + @media screen and (min-width: 64em) { + .menu.large-horizontal { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; } + .menu.large-horizontal > li { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; } + .menu.large-vertical { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .menu.large-vertical > li { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + .menu.large-vertical > li > a { + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; } } + .menu.simple li { + line-height: 1; + display: inline-block; + margin-right: 1rem; } + .menu.simple a { + padding: 0; } + .menu.align-right { + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; } + .menu.expanded > li { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } + .menu.expanded > li:first-child:last-child { + width: 100%; } + .menu.icon-top > li > a { + -ms-flex-flow: column nowrap; + flex-flow: column nowrap; } + .menu.icon-top > li > a img, + .menu.icon-top > li > a i, + .menu.icon-top > li > a svg { + -ms-flex-item-align: stretch; + align-self: stretch; + text-align: center; + margin-bottom: 0.25rem; } + .menu.nested { + margin-left: 1rem; } + .menu .active > a { + color: #fefefe; + background: #2199e8; } + +.menu-text { + font-weight: bold; + color: inherit; + line-height: 1; + padding-top: 0; + padding-bottom: 0; + padding: 0.7rem 1rem; } + +.menu-centered { + text-align: center; } + .menu-centered > .menu { + display: inline-block; } + +.no-js [data-responsive-menu] ul { + display: none; } + +.menu-icon { + position: relative; + display: inline-block; + vertical-align: middle; + cursor: pointer; + width: 20px; + height: 16px; } + .menu-icon::after { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 2px; + background: #fefefe; + top: 0; + left: 0; + -webkit-box-shadow: 0 7px 0 #fefefe, 0 14px 0 #fefefe; + box-shadow: 0 7px 0 #fefefe, 0 14px 0 #fefefe; } + .menu-icon:hover::after { + background: #cacaca; + -webkit-box-shadow: 0 7px 0 #cacaca, 0 14px 0 #cacaca; + box-shadow: 0 7px 0 #cacaca, 0 14px 0 #cacaca; } + +.menu-icon.dark { + position: relative; + display: inline-block; + vertical-align: middle; + cursor: pointer; + width: 20px; + height: 16px; } + .menu-icon.dark::after { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 2px; + background: #0a0a0a; + top: 0; + left: 0; + -webkit-box-shadow: 0 7px 0 #0a0a0a, 0 14px 0 #0a0a0a; + box-shadow: 0 7px 0 #0a0a0a, 0 14px 0 #0a0a0a; } + .menu-icon.dark:hover::after { + background: #8a8a8a; + -webkit-box-shadow: 0 7px 0 #8a8a8a, 0 14px 0 #8a8a8a; + box-shadow: 0 7px 0 #8a8a8a, 0 14px 0 #8a8a8a; } + +.is-drilldown { + position: relative; + overflow: hidden; } + .is-drilldown li { + display: block !important; } + +.is-drilldown-submenu { + position: absolute; + top: 0; + left: 100%; + z-index: -1; + width: 100%; + background: #fefefe; + -webkit-transition: -webkit-transform 0.15s linear; + transition: transform 0.15s linear; } + .is-drilldown-submenu.is-active { + z-index: 1; + display: block; + -webkit-transform: translateX(-100%); + -ms-transform: translateX(-100%); + transform: translateX(-100%); } + .is-drilldown-submenu.is-closing { + -webkit-transform: translateX(100%); + -ms-transform: translateX(100%); + transform: translateX(100%); } + +.is-drilldown-submenu-parent > a { + position: relative; } + .is-drilldown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; + position: absolute; + top: 50%; + margin-top: -6px; + right: 1rem; } + +.js-drilldown-back > a::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; + border-left-width: 0; + display: inline-block; + vertical-align: middle; + margin-right: 0.75rem; } + +.dropdown-pane { + background-color: #fefefe; + border: 1px solid #cacaca; + border-radius: 0; + display: block; + font-size: 1rem; + padding: 1rem; + position: absolute; + visibility: hidden; + width: 300px; + z-index: 10; } + .dropdown-pane.is-open { + visibility: visible; } + +.dropdown-pane.tiny { + width: 100px; } + +.dropdown-pane.small { + width: 200px; } + +.dropdown-pane.large { + width: 400px; } + +.dropdown.menu > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + +.dropdown.menu > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + +.dropdown.menu > li.is-dropdown-submenu-parent > a { + padding-right: 1.5rem; + position: relative; } + +.dropdown.menu > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + right: 5px; + margin-top: -2px; } + +[data-whatinput='mouse'] .dropdown.menu a { + outline: 0; } + +.no-js .dropdown.menu ul { + display: none; } + +.dropdown.menu.vertical > li .is-dropdown-submenu { + top: 0; } + +.dropdown.menu.vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + +.dropdown.menu.vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + +.dropdown.menu.vertical > li > a::after { + right: 14px; + margin-top: -3px; } + +.dropdown.menu.vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + +.dropdown.menu.vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } + +@media screen and (min-width: 40em) { + .dropdown.menu.medium-horizontal > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + .dropdown.menu.medium-horizontal > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a { + padding-right: 1.5rem; + position: relative; } + .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + right: 5px; + margin-top: -2px; } + .dropdown.menu.medium-vertical > li .is-dropdown-submenu { + top: 0; } + .dropdown.menu.medium-vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .dropdown.menu.medium-vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + .dropdown.menu.medium-vertical > li > a::after { + right: 14px; + margin-top: -3px; } + .dropdown.menu.medium-vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .dropdown.menu.medium-vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } } + +@media screen and (min-width: 64em) { + .dropdown.menu.large-horizontal > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + .dropdown.menu.large-horizontal > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a { + padding-right: 1.5rem; + position: relative; } + .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + right: 5px; + margin-top: -2px; } + .dropdown.menu.large-vertical > li .is-dropdown-submenu { + top: 0; } + .dropdown.menu.large-vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .dropdown.menu.large-vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + .dropdown.menu.large-vertical > li > a::after { + right: 14px; + margin-top: -3px; } + .dropdown.menu.large-vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .dropdown.menu.large-vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } } + +.dropdown.menu.align-right .is-dropdown-submenu.first-sub { + top: 100%; + left: auto; + right: 0; } + +.is-dropdown-menu.vertical { + width: 100px; } + .is-dropdown-menu.vertical.align-right { + float: right; } + +.is-dropdown-submenu-parent { + position: relative; } + .is-dropdown-submenu-parent a::after { + position: absolute; + top: 50%; + right: 5px; + margin-top: -2px; } + .is-dropdown-submenu-parent.opens-inner > .is-dropdown-submenu { + top: 100%; + left: auto; } + .is-dropdown-submenu-parent.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .is-dropdown-submenu-parent.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + +.is-dropdown-submenu { + display: none; + position: absolute; + top: 0; + left: 100%; + min-width: 200px; + z-index: 1; + background: #fefefe; + border: 1px solid #cacaca; } + .is-dropdown-submenu .is-dropdown-submenu-parent > a::after { + right: 14px; + margin-top: -3px; } + .is-dropdown-submenu .is-dropdown-submenu-parent.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .is-dropdown-submenu .is-dropdown-submenu-parent.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } + .is-dropdown-submenu .is-dropdown-submenu { + margin-top: -1px; } + .is-dropdown-submenu > li { + width: 100%; } + .is-dropdown-submenu.js-dropdown-active { + display: block; } + +.flex-video { + position: relative; + height: 0; + padding-bottom: 75%; + margin-bottom: 1rem; + overflow: hidden; } + .flex-video iframe, + .flex-video object, + .flex-video embed, + .flex-video video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; } + .flex-video.widescreen { + padding-bottom: 56.25%; } + .flex-video.vimeo { + padding-top: 0; } + +.label { + display: inline-block; + padding: 0.33333rem 0.5rem; + font-size: 0.8rem; + line-height: 1; + white-space: nowrap; + cursor: default; + border-radius: 0; + background: #2199e8; + color: #fefefe; } + .label.secondary { + background: #777; + color: #fefefe; } + .label.success { + background: #3adb76; + color: #fefefe; } + .label.warning { + background: #ffae00; + color: #fefefe; } + .label.alert { + background: #ec5840; + color: #fefefe; } + +.media-object { + margin-bottom: 1rem; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; } + .media-object img { + max-width: none; } + @media screen and (max-width: 39.9375em) { + .media-object.stack-for-small { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } } + @media screen and (max-width: 39.9375em) { + .media-object.stack-for-small .media-object-section { + padding: 0; + padding-bottom: 1rem; + -ms-flex-preferred-size: 100%; + flex-basis: 100%; + max-width: 100%; } + .media-object.stack-for-small .media-object-section img { + width: 100%; } } + +.media-object-section { + -webkit-box-flex: 0; + -ms-flex: 0 1 auto; + flex: 0 1 auto; } + .media-object-section:first-child { + padding-right: 1rem; } + .media-object-section:last-child:not(:nth-child(2)) { + padding-left: 1rem; } + .media-object-section > :last-child { + margin-bottom: 0; } + .media-object-section.main-section { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } + +html, +body { + height: 100%; } + +.off-canvas-wrapper { + width: 100%; + overflow-x: hidden; + position: relative; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-overflow-scrolling: auto; } + +.off-canvas-wrapper-inner { + position: relative; + width: 100%; + min-height: 100%; + -webkit-transition: -webkit-transform 0.5s ease; + transition: transform 0.5s ease; } + .off-canvas-wrapper-inner::before, .off-canvas-wrapper-inner::after { + content: ' '; + display: table; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .off-canvas-wrapper-inner::after { + clear: both; } + +.off-canvas-content, +.off-canvas-content { + min-height: 100%; + background: #fefefe; + -webkit-transition: -webkit-transform 0.5s ease; + transition: transform 0.5s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + z-index: 1; + padding-bottom: 0.1px; + -webkit-box-shadow: 0 0 10px rgba(10, 10, 10, 0.5); + box-shadow: 0 0 10px rgba(10, 10, 10, 0.5); } + +.js-off-canvas-exit { + display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(254, 254, 254, 0.25); + cursor: pointer; + -webkit-transition: background 0.5s ease; + transition: background 0.5s ease; } + +.off-canvas { + position: absolute; + background: #e6e6e6; + z-index: -1; + max-height: 100%; + overflow-y: auto; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); } + [data-whatinput='mouse'] .off-canvas { + outline: 0; } + .off-canvas.position-left { + left: -250px; + top: 0; + width: 250px; } + .is-open-left { + -webkit-transform: translateX(250px); + -ms-transform: translateX(250px); + transform: translateX(250px); } + .off-canvas.position-right { + right: -250px; + top: 0; + width: 250px; } + .is-open-right { + -webkit-transform: translateX(-250px); + -ms-transform: translateX(-250px); + transform: translateX(-250px); } + +@media screen and (min-width: 40em) { + .position-left.reveal-for-medium { + left: 0; + z-index: auto; + position: fixed; } + .position-left.reveal-for-medium ~ .off-canvas-content { + margin-left: 250px; } + .position-right.reveal-for-medium { + right: 0; + z-index: auto; + position: fixed; } + .position-right.reveal-for-medium ~ .off-canvas-content { + margin-right: 250px; } } + +@media screen and (min-width: 64em) { + .position-left.reveal-for-large { + left: 0; + z-index: auto; + position: fixed; } + .position-left.reveal-for-large ~ .off-canvas-content { + margin-left: 250px; } + .position-right.reveal-for-large { + right: 0; + z-index: auto; + position: fixed; } + .position-right.reveal-for-large ~ .off-canvas-content { + margin-right: 250px; } } + +.orbit { + position: relative; } + +.orbit-container { + position: relative; + margin: 0; + overflow: hidden; + list-style: none; } + +.orbit-slide { + width: 100%; + max-height: 100%; } + .orbit-slide.no-motionui.is-active { + top: 0; + left: 0; } + +.orbit-figure { + margin: 0; } + +.orbit-image { + margin: 0; + width: 100%; + max-width: 100%; } + +.orbit-caption { + position: absolute; + bottom: 0; + width: 100%; + padding: 1rem; + margin-bottom: 0; + color: #fefefe; + background-color: rgba(10, 10, 10, 0.5); } + +.orbit-previous, .orbit-next { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + z-index: 10; + padding: 1rem; + color: #fefefe; } + [data-whatinput='mouse'] .orbit-previous, [data-whatinput='mouse'] .orbit-next { + outline: 0; } + .orbit-previous:hover, .orbit-next:hover, .orbit-previous:active, .orbit-next:active, .orbit-previous:focus, .orbit-next:focus { + background-color: rgba(10, 10, 10, 0.5); } + +.orbit-previous { + left: 0; } + +.orbit-next { + left: auto; + right: 0; } + +.orbit-bullets { + position: relative; + margin-top: 0.8rem; + margin-bottom: 0.8rem; + text-align: center; } + [data-whatinput='mouse'] .orbit-bullets { + outline: 0; } + .orbit-bullets button { + width: 1.2rem; + height: 1.2rem; + margin: 0.1rem; + background-color: #cacaca; + border-radius: 50%; } + .orbit-bullets button:hover { + background-color: #8a8a8a; } + .orbit-bullets button.is-active { + background-color: #8a8a8a; } + +.pagination { + margin-left: 0; + margin-bottom: 1rem; } + .pagination::before, .pagination::after { + content: ' '; + display: table; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .pagination::after { + clear: both; } + .pagination li { + font-size: 0.875rem; + margin-right: 0.0625rem; + border-radius: 0; + display: none; } + .pagination li:last-child, .pagination li:first-child { + display: inline-block; } + @media screen and (min-width: 40em) { + .pagination li { + display: inline-block; } } + .pagination a, + .pagination button { + color: #0a0a0a; + display: block; + padding: 0.1875rem 0.625rem; + border-radius: 0; } + .pagination a:hover, + .pagination button:hover { + background: #e6e6e6; } + .pagination .current { + padding: 0.1875rem 0.625rem; + background: #2199e8; + color: #fefefe; + cursor: default; } + .pagination .disabled { + padding: 0.1875rem 0.625rem; + color: #cacaca; + cursor: not-allowed; } + .pagination .disabled:hover { + background: transparent; } + .pagination .ellipsis::after { + content: '\2026'; + padding: 0.1875rem 0.625rem; + color: #0a0a0a; } + +.pagination-previous a::before, +.pagination-previous.disabled::before { + content: '\00ab'; + display: inline-block; + margin-right: 0.5rem; } + +.pagination-next a::after, +.pagination-next.disabled::after { + content: '\00bb'; + display: inline-block; + margin-left: 0.5rem; } + +.progress { + background-color: #cacaca; + height: 1rem; + margin-bottom: 1rem; + border-radius: 0; } + .progress.primary .progress-meter { + background-color: #2199e8; } + .progress.secondary .progress-meter { + background-color: #777; } + .progress.success .progress-meter { + background-color: #3adb76; } + .progress.warning .progress-meter { + background-color: #ffae00; } + .progress.alert .progress-meter { + background-color: #ec5840; } + +.progress-meter { + position: relative; + display: block; + width: 0%; + height: 100%; + background-color: #2199e8; } + +.progress-meter-text { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + position: absolute; + margin: 0; + font-size: 0.75rem; + font-weight: bold; + color: #fefefe; + white-space: nowrap; } + +.slider { + position: relative; + height: 0.5rem; + margin-top: 1.25rem; + margin-bottom: 2.25rem; + background-color: #e6e6e6; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -ms-touch-action: none; + touch-action: none; } + +.slider-fill { + position: absolute; + top: 0; + left: 0; + display: inline-block; + max-width: 100%; + height: 0.5rem; + background-color: #cacaca; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + .slider-fill.is-dragging { + -webkit-transition: all 0s linear; + transition: all 0s linear; } + +.slider-handle { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + position: absolute; + left: 0; + z-index: 1; + display: inline-block; + width: 1.4rem; + height: 1.4rem; + background-color: #2199e8; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -ms-touch-action: manipulation; + touch-action: manipulation; + border-radius: 0; } + [data-whatinput='mouse'] .slider-handle { + outline: 0; } + .slider-handle:hover { + background-color: #1583cc; } + .slider-handle.is-dragging { + -webkit-transition: all 0s linear; + transition: all 0s linear; } + +.slider.disabled, +.slider[disabled] { + opacity: 0.25; + cursor: not-allowed; } + +.slider.vertical { + display: inline-block; + width: 0.5rem; + height: 12.5rem; + margin: 0 1.25rem; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); } + .slider.vertical .slider-fill { + top: 0; + width: 0.5rem; + max-height: 100%; } + .slider.vertical .slider-handle { + position: absolute; + top: 0; + left: 50%; + width: 1.4rem; + height: 1.4rem; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + +.sticky-container { + position: relative; } + +.sticky { + position: absolute; + z-index: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.sticky.is-stuck { + position: fixed; + z-index: 5; } + .sticky.is-stuck.is-at-top { + top: 0; } + .sticky.is-stuck.is-at-bottom { + bottom: 0; } + +.sticky.is-anchored { + position: absolute; + left: auto; + right: auto; } + .sticky.is-anchored.is-at-bottom { + bottom: 0; } + +body.is-reveal-open { + overflow: hidden; } + +html.is-reveal-open, +html.is-reveal-open body { + min-height: 100%; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +.reveal-overlay { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1005; + background-color: rgba(10, 10, 10, 0.45); + overflow-y: scroll; } + +.reveal { + display: none; + z-index: 1006; + padding: 1rem; + border: 1px solid #cacaca; + background-color: #fefefe; + border-radius: 0; + position: relative; + top: 100px; + margin-left: auto; + margin-right: auto; + overflow-y: auto; } + [data-whatinput='mouse'] .reveal { + outline: 0; } + @media screen and (min-width: 40em) { + .reveal { + min-height: 0; } } + .reveal .column, .reveal .columns, + .reveal .columns { + min-width: 0; } + .reveal > :last-child { + margin-bottom: 0; } + @media screen and (min-width: 40em) { + .reveal { + width: 600px; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal .reveal { + left: auto; + right: auto; + margin: 0 auto; } } + .reveal.collapse { + padding: 0; } + @media screen and (min-width: 40em) { + .reveal.tiny { + width: 30%; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal.small { + width: 50%; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal.large { + width: 90%; + max-width: 75rem; } } + .reveal.full { + top: 0; + left: 0; + width: 100%; + height: 100%; + height: 100vh; + min-height: 100vh; + max-width: none; + margin-left: 0; + border: 0; + border-radius: 0; } + @media screen and (max-width: 39.9375em) { + .reveal { + top: 0; + left: 0; + width: 100%; + height: 100%; + height: 100vh; + min-height: 100vh; + max-width: none; + margin-left: 0; + border: 0; + border-radius: 0; } } + .reveal.without-overlay { + position: fixed; } + +.switch { + height: 2rem; + margin-bottom: 1rem; + outline: 0; + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + color: #fefefe; + font-weight: bold; + font-size: 0.875rem; } + +.switch-input { + opacity: 0; + position: absolute; + margin-bottom: 0; } + +.switch-paddle { + background: #cacaca; + cursor: pointer; + display: block; + position: relative; + width: 4rem; + height: 2rem; + -webkit-transition: all 0.25s ease-out; + transition: all 0.25s ease-out; + border-radius: 0; + color: inherit; + font-weight: inherit; } + input + .switch-paddle { + margin: 0; } + .switch-paddle::after { + background: #fefefe; + content: ''; + display: block; + position: absolute; + height: 1.5rem; + left: 0.25rem; + top: 0.25rem; + width: 1.5rem; + -webkit-transition: all 0.25s ease-out; + transition: all 0.25s ease-out; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + border-radius: 0; } + input:checked ~ .switch-paddle { + background: #2199e8; } + input:checked ~ .switch-paddle::after { + left: 2.25rem; } + [data-whatinput='mouse'] input:focus ~ .switch-paddle { + outline: 0; } + +.switch-active, .switch-inactive { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.switch-active { + left: 8%; + display: none; } + input:checked + label > .switch-active { + display: block; } + +.switch-inactive { + right: 15%; } + input:checked + label > .switch-inactive { + display: none; } + +.switch.tiny { + height: 1.5rem; } + .switch.tiny .switch-paddle { + width: 3rem; + height: 1.5rem; + font-size: 0.625rem; } + .switch.tiny .switch-paddle::after { + width: 1rem; + height: 1rem; } + .switch.tiny input:checked ~ .switch-paddle::after { + left: 1.75rem; } + +.switch.small { + height: 1.75rem; } + .switch.small .switch-paddle { + width: 3.5rem; + height: 1.75rem; + font-size: 0.75rem; } + .switch.small .switch-paddle::after { + width: 1.25rem; + height: 1.25rem; } + .switch.small input:checked ~ .switch-paddle::after { + left: 2rem; } + +.switch.large { + height: 2.5rem; } + .switch.large .switch-paddle { + width: 5rem; + height: 2.5rem; + font-size: 1rem; } + .switch.large .switch-paddle::after { + width: 2rem; + height: 2rem; } + .switch.large input:checked ~ .switch-paddle::after { + left: 2.75rem; } + +table { + width: 100%; + margin-bottom: 1rem; + border-radius: 0; } + table thead, + table tbody, + table tfoot { + border: 1px solid #f1f1f1; + background-color: #fefefe; } + table caption { + font-weight: bold; + padding: 0.5rem 0.625rem 0.625rem; } + table thead { + background: #f8f8f8; + color: #0a0a0a; } + table tfoot { + background: #f1f1f1; + color: #0a0a0a; } + table thead tr, + table tfoot tr { + background: transparent; } + table thead th, + table thead td, + table tfoot th, + table tfoot td { + padding: 0.5rem 0.625rem 0.625rem; + font-weight: bold; + text-align: left; } + table tbody tr:nth-child(even) { + background-color: #f1f1f1; } + table tbody th, + table tbody td { + padding: 0.5rem 0.625rem 0.625rem; } + +@media screen and (max-width: 63.9375em) { + table.stack thead { + display: none; } + table.stack tfoot { + display: none; } + table.stack tr, + table.stack th, + table.stack td { + display: block; } + table.stack td { + border-top: 0; } } + +table.scroll { + display: block; + width: 100%; + overflow-x: auto; } + +table.hover thead tr:hover { + background-color: #f3f3f3; } + +table.hover tfoot tr:hover { + background-color: #ececec; } + +table.hover tbody tr:hover { + background-color: #f9f9f9; } + +table.hover tbody tr:nth-of-type(even):hover { + background-color: #ececec; } + +.table-scroll { + overflow-x: auto; } + .table-scroll table { + width: auto; } + +.tabs { + margin: 0; + list-style-type: none; + background: #fefefe; + border: 1px solid #e6e6e6; } + .tabs::before, .tabs::after { + content: ' '; + display: table; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .tabs::after { + clear: both; } + +.tabs.vertical > li { + width: auto; + float: none; + display: block; } + +.tabs.simple > li > a { + padding: 0; } + .tabs.simple > li > a:hover { + background: transparent; } + +.tabs.primary { + background: #2199e8; } + .tabs.primary > li > a { + color: #fefefe; } + .tabs.primary > li > a:hover, .tabs.primary > li > a:focus { + background: #1893e4; } + +.tabs-title { + float: left; } + .tabs-title > a { + display: block; + padding: 1.25rem 1.5rem; + line-height: 1; + font-size: 0.75rem; } + .tabs-title > a:hover { + background: #fefefe; } + .tabs-title > a:focus, .tabs-title > a[aria-selected='true'] { + background: #e6e6e6; } + +.tabs-content { + background: #fefefe; + -webkit-transition: all 0.5s ease; + transition: all 0.5s ease; + border: 1px solid #e6e6e6; + border-top: 0; } + +.tabs-content.vertical { + border: 1px solid #e6e6e6; + border-left: 0; } + +.tabs-panel { + display: none; + padding: 1rem; } + .tabs-panel.is-active { + display: block; } + +.thumbnail { + border: solid 4px #fefefe; + -webkit-box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2); + box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2); + display: inline-block; + line-height: 0; + max-width: 100%; + -webkit-transition: -webkit-box-shadow 200ms ease-out; + transition: box-shadow 200ms ease-out; + border-radius: 0; + margin-bottom: 1rem; } + .thumbnail:hover, .thumbnail:focus { + -webkit-box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); + box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); } + +.title-bar { + background: #0a0a0a; + color: #fefefe; + padding: 0.5rem; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; } + .title-bar .menu-icon { + margin-left: 0.25rem; + margin-right: 0.25rem; } + +.title-bar-left, +.title-bar-right { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0px; } + +.title-bar-right { + text-align: right; } + +.title-bar-title { + font-weight: bold; + vertical-align: middle; + display: inline-block; } + +.has-tip { + border-bottom: dotted 1px #8a8a8a; + font-weight: bold; + position: relative; + display: inline-block; + cursor: help; } + +.tooltip { + background-color: #0a0a0a; + color: #fefefe; + font-size: 80%; + padding: 0.75rem; + position: absolute; + z-index: 10; + top: calc(100% + 0.6495rem); + max-width: 10rem !important; + border-radius: 0; } + .tooltip::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent transparent #0a0a0a; + border-bottom-style: solid; + border-top-width: 0; + bottom: 100%; + position: absolute; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + .tooltip.top::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: #0a0a0a transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + top: 100%; + bottom: auto; } + .tooltip.left::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent transparent transparent #0a0a0a; + border-left-style: solid; + border-right-width: 0; + bottom: auto; + left: 100%; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .tooltip.right::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent #0a0a0a transparent transparent; + border-right-style: solid; + border-left-width: 0; + bottom: auto; + left: auto; + right: 100%; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.top-bar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + padding: 0.5rem; + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .top-bar, + .top-bar ul { + background-color: #e6e6e6; } + .top-bar input { + max-width: 200px; + margin-right: 1rem; } + .top-bar .input-group-field { + width: 100%; + margin-right: 0; } + .top-bar input.button { + width: auto; } + .top-bar .top-bar-left, + .top-bar .top-bar-right { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } + @media screen and (min-width: 40em) { + .top-bar { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; } + .top-bar .top-bar-left { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; } + .top-bar .top-bar-right { + -webkit-box-flex: 0; + -ms-flex: 0 1 auto; + flex: 0 1 auto; } } + @media screen and (max-width: 63.9375em) { + .top-bar.stacked-for-medium { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .top-bar.stacked-for-medium .top-bar-left, + .top-bar.stacked-for-medium .top-bar-right { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } } + @media screen and (max-width: 74.9375em) { + .top-bar.stacked-for-large { + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .top-bar.stacked-for-large .top-bar-left, + .top-bar.stacked-for-large .top-bar-right { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; } } + +.top-bar-title { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + margin-right: 1rem; } + +.top-bar-left, +.top-bar-right { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; } + +.hide { + display: none !important; } + +.invisible { + visibility: hidden; } + +@media screen and (max-width: 39.9375em) { + .hide-for-small-only { + display: none !important; } } + +@media screen and (max-width: 0em), screen and (min-width: 40em) { + .show-for-small-only { + display: none !important; } } + +@media screen and (min-width: 40em) { + .hide-for-medium { + display: none !important; } } + +@media screen and (max-width: 39.9375em) { + .show-for-medium { + display: none !important; } } + +@media screen and (min-width: 40em) and (max-width: 63.9375em) { + .hide-for-medium-only { + display: none !important; } } + +@media screen and (max-width: 39.9375em), screen and (min-width: 64em) { + .show-for-medium-only { + display: none !important; } } + +@media screen and (min-width: 64em) { + .hide-for-large { + display: none !important; } } + +@media screen and (max-width: 63.9375em) { + .show-for-large { + display: none !important; } } + +@media screen and (min-width: 64em) and (max-width: 74.9375em) { + .hide-for-large-only { + display: none !important; } } + +@media screen and (max-width: 63.9375em), screen and (min-width: 75em) { + .show-for-large-only { + display: none !important; } } + +.show-for-sr, +.show-on-focus { + position: absolute !important; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); } + +.show-on-focus:active, .show-on-focus:focus { + position: static !important; + height: auto; + width: auto; + overflow: visible; + clip: auto; } + +.show-for-landscape, +.hide-for-portrait { + display: block !important; } + @media screen and (orientation: landscape) { + .show-for-landscape, + .hide-for-portrait { + display: block !important; } } + @media screen and (orientation: portrait) { + .show-for-landscape, + .hide-for-portrait { + display: none !important; } } + +.hide-for-landscape, +.show-for-portrait { + display: none !important; } + @media screen and (orientation: landscape) { + .hide-for-landscape, + .show-for-portrait { + display: none !important; } } + @media screen and (orientation: portrait) { + .hide-for-landscape, + .show-for-portrait { + display: block !important; } } + +.float-left { + float: left !important; } + +.float-right { + float: right !important; } + +.float-center { + display: block; + margin-left: auto; + margin-right: auto; } + +.clearfix::before, .clearfix::after { + content: ' '; + display: table; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + +.clearfix::after { + clear: both; } + +.align-right { + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; } + +.align-center { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + +.align-justify { + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; } + +.align-spaced { + -ms-flex-pack: distribute; + justify-content: space-around; } + +.align-top { + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; } + +.align-self-top { + -ms-flex-item-align: start; + align-self: flex-start; } + +.align-bottom { + -webkit-box-align: end; + -ms-flex-align: end; + align-items: flex-end; } + +.align-self-bottom { + -ms-flex-item-align: end; + align-self: flex-end; } + +.align-middle { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + +.align-self-middle { + -ms-flex-item-align: center; + align-self: center; } + +.align-stretch { + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; } + +.align-self-stretch { + -ms-flex-item-align: stretch; + align-self: stretch; } + +.small-order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + +.small-order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; } + +.small-order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; } + +.small-order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; } + +.small-order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; } + +.small-order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; } + +@media screen and (min-width: 40em) { + .medium-order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .medium-order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; } + .medium-order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; } + .medium-order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; } + .medium-order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; } + .medium-order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; } } + +@media screen and (min-width: 64em) { + .large-order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; } + .large-order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; } + .large-order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; } + .large-order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; } + .large-order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; } + .large-order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; } } + +/*# sourceMappingURL=foundation-flex.css.map */ diff --git a/sopds_web_backend/static/css/foundation-flex.min.css b/sopds_web_backend/static/css/foundation-flex.min.css new file mode 100644 index 0000000000000000000000000000000000000000..8bc88de07fa89707447126e4309039e631b462f3 --- /dev/null +++ b/sopds_web_backend/static/css/foundation-flex.min.css @@ -0,0 +1,2 @@ +@charset "UTF-8"; +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:not-allowed}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{font-size:100%;box-sizing:border-box}*,:after,:before{box-sizing:inherit}body{padding:0;margin:0;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;color:#0a0a0a;background:#fefefe;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}img{max-width:100%;height:auto;-ms-interpolation-mode:bicubic;display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px;border-radius:0}select{width:100%;border-radius:0}#map_canvas embed,#map_canvas img,#map_canvas object,.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;background:transparent;padding:0;border:0;border-radius:0;line-height:1}[data-whatinput=mouse] button{outline:0}.is-visible{display:block!important}.is-hidden{display:none!important}.row{max-width:75rem;margin-left:auto;margin-right:auto;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.row .row{margin-left:-.625rem;margin-right:-.625rem}@media screen and (min-width:40em){.row .row{margin-left:-.9375rem;margin-right:-.9375rem}}.row.expanded{max-width:none}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0}.row.collapse>.column>.row,.row.collapse>.columns>.row,.row.is-collapse-child{margin-left:0;margin-right:0}.column,.columns{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px;padding-left:.625rem;padding-right:.625rem;min-width:0}@media screen and (min-width:40em){.column,.columns{padding-left:.9375rem;padding-right:.9375rem}}.column.row.row,.row.row.columns{float:none;display:block}.row .column.row.row,.row .row.row.columns{padding-left:0;padding-right:0;margin-left:0;margin-right:0}.small-1{-webkit-box-flex:0;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.small-offset-0{margin-left:0}.small-2{-webkit-box-flex:0;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.small-offset-1{margin-left:8.33333%}.small-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.small-offset-2{margin-left:16.66667%}.small-4{-webkit-box-flex:0;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.small-offset-3{margin-left:25%}.small-5{-webkit-box-flex:0;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.small-offset-4{margin-left:33.33333%}.small-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.small-offset-5{margin-left:41.66667%}.small-7{-webkit-box-flex:0;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.small-offset-6{margin-left:50%}.small-8{-webkit-box-flex:0;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.small-offset-7{margin-left:58.33333%}.small-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.small-offset-8{margin-left:66.66667%}.small-10{-webkit-box-flex:0;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.small-offset-9{margin-left:75%}.small-11{-webkit-box-flex:0;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.small-offset-10{margin-left:83.33333%}.small-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.small-offset-11{margin-left:91.66667%}.small-up-1{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-1>.column,.small-up-1>.columns{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.small-up-2{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-2>.column,.small-up-2>.columns{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.small-up-3{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-3>.column,.small-up-3>.columns{-webkit-box-flex:0;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.small-up-4{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-4>.column,.small-up-4>.columns{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.small-up-5{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-5>.column,.small-up-5>.columns{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.small-up-6{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-6>.column,.small-up-6>.columns{-webkit-box-flex:0;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.small-up-7{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-7>.column,.small-up-7>.columns{-webkit-box-flex:0;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%;max-width:14.28571%}.small-up-8{-ms-flex-wrap:wrap;flex-wrap:wrap}.small-up-8>.column,.small-up-8>.columns{-webkit-box-flex:0;-ms-flex:0 0 12.5%;flex:0 0 12.5%;max-width:12.5%}.small-collapse>.column,.small-collapse>.columns{padding-left:0;padding-right:0}.small-uncollapse>.column,.small-uncollapse>.columns{padding-left:.625rem;padding-right:.625rem}@media screen and (min-width:40em){.medium-1{-webkit-box-flex:0;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.medium-offset-0{margin-left:0}.medium-2{-webkit-box-flex:0;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.medium-offset-1{margin-left:8.33333%}.medium-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.medium-offset-2{margin-left:16.66667%}.medium-4{-webkit-box-flex:0;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.medium-offset-3{margin-left:25%}.medium-5{-webkit-box-flex:0;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.medium-offset-4{margin-left:33.33333%}.medium-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.medium-offset-5{margin-left:41.66667%}.medium-7{-webkit-box-flex:0;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.medium-offset-6{margin-left:50%}.medium-8{-webkit-box-flex:0;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.medium-offset-7{margin-left:58.33333%}.medium-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.medium-offset-8{margin-left:66.66667%}.medium-10{-webkit-box-flex:0;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.medium-offset-9{margin-left:75%}.medium-11{-webkit-box-flex:0;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.medium-offset-10{margin-left:83.33333%}.medium-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.medium-offset-11{margin-left:91.66667%}.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.medium-up-1{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-1>.column,.medium-up-1>.columns{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.medium-up-2{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-2>.column,.medium-up-2>.columns{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.medium-up-3{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-3>.column,.medium-up-3>.columns{-webkit-box-flex:0;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.medium-up-4{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-4>.column,.medium-up-4>.columns{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.medium-up-5{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-5>.column,.medium-up-5>.columns{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.medium-up-6{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-6>.column,.medium-up-6>.columns{-webkit-box-flex:0;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.medium-up-7{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-7>.column,.medium-up-7>.columns{-webkit-box-flex:0;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%;max-width:14.28571%}.medium-up-8{-ms-flex-wrap:wrap;flex-wrap:wrap}.medium-up-8>.column,.medium-up-8>.columns{-webkit-box-flex:0;-ms-flex:0 0 12.5%;flex:0 0 12.5%;max-width:12.5%}}@media screen and (min-width:40em) and (min-width:40em){.medium-expand{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}}.row.medium-unstack>.column,.row.medium-unstack>.columns{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%}@media screen and (min-width:40em){.row.medium-unstack>.column,.row.medium-unstack>.columns{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}}@media screen and (min-width:40em){.medium-collapse>.column,.medium-collapse>.columns{padding-left:0;padding-right:0}.medium-uncollapse>.column,.medium-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}}@media screen and (min-width:64em){.large-1{-webkit-box-flex:0;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.large-offset-0{margin-left:0}.large-2{-webkit-box-flex:0;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.large-offset-1{margin-left:8.33333%}.large-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.large-offset-2{margin-left:16.66667%}.large-4{-webkit-box-flex:0;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.large-offset-3{margin-left:25%}.large-5{-webkit-box-flex:0;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.large-offset-4{margin-left:33.33333%}.large-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.large-offset-5{margin-left:41.66667%}.large-7{-webkit-box-flex:0;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.large-offset-6{margin-left:50%}.large-8{-webkit-box-flex:0;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.large-offset-7{margin-left:58.33333%}.large-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.large-offset-8{margin-left:66.66667%}.large-10{-webkit-box-flex:0;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.large-offset-9{margin-left:75%}.large-11{-webkit-box-flex:0;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.large-offset-10{margin-left:83.33333%}.large-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.large-offset-11{margin-left:91.66667%}.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.large-up-1{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-1>.column,.large-up-1>.columns{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.large-up-2{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-2>.column,.large-up-2>.columns{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.large-up-3{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-3>.column,.large-up-3>.columns{-webkit-box-flex:0;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.large-up-4{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-4>.column,.large-up-4>.columns{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.large-up-5{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-5>.column,.large-up-5>.columns{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.large-up-6{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-6>.column,.large-up-6>.columns{-webkit-box-flex:0;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.large-up-7{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-7>.column,.large-up-7>.columns{-webkit-box-flex:0;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%;max-width:14.28571%}.large-up-8{-ms-flex-wrap:wrap;flex-wrap:wrap}.large-up-8>.column,.large-up-8>.columns{-webkit-box-flex:0;-ms-flex:0 0 12.5%;flex:0 0 12.5%;max-width:12.5%}}@media screen and (min-width:64em) and (min-width:64em){.large-expand{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}}.row.large-unstack>.column,.row.large-unstack>.columns{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%}@media screen and (min-width:64em){.row.large-unstack>.column,.row.large-unstack>.columns{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}}@media screen and (min-width:64em){.large-collapse>.column,.large-collapse>.columns{padding-left:0;padding-right:0}.large-uncollapse>.column,.large-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}}.shrink{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;max-width:100%}.align-top.columns,.column.align-top{-ms-flex-item-align:start;align-self:flex-start}.align-bottom.columns,.column.align-bottom{-ms-flex-item-align:end;align-self:flex-end}.align-middle.columns,.column.align-middle{-ms-flex-item-align:center;align-self:center}.align-stretch.columns,.column.align-stretch{-ms-flex-item-align:stretch;align-self:stretch}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{font-size:inherit;line-height:1.6;margin-bottom:1rem;text-rendering:optimizeLegibility}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}h1,h2,h3,h4,h5,h6{font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;font-style:normal;color:inherit;text-rendering:optimizeLegibility;margin-top:0;margin-bottom:.5rem;line-height:1.4}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.1875rem}h4{font-size:1.125rem}h5{font-size:1.0625rem}h6{font-size:1rem}@media screen and (min-width:40em){h1{font-size:3rem}h2{font-size:2.5rem}h3{font-size:1.9375rem}h4{font-size:1.5625rem}h5{font-size:1.25rem}h6{font-size:1rem}}a{color:#2199e8;text-decoration:none;line-height:inherit;cursor:pointer}a:focus,a:hover{color:#1585cf}a img{border:0}hr{max-width:75rem;height:0;border-right:0;border-top:0;border-bottom:1px solid #cacaca;border-left:0;margin:1.25rem auto;clear:both}dl,ol,ul{line-height:1.6;margin-bottom:1rem;list-style-position:outside}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-left:1.25rem;margin-bottom:0}dl{margin-bottom:1rem}dl dt{margin-bottom:.3rem;font-weight:700}blockquote{margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem;border-left:1px solid #cacaca}blockquote,blockquote p{line-height:1.6;color:#8a8a8a}cite{display:block;font-size:.8125rem;color:#8a8a8a}cite:before{content:'\2014 \0020'}abbr{color:#0a0a0a;cursor:help;border-bottom:1px dotted #0a0a0a}code{font-weight:400;border:1px solid #cacaca;padding:.125rem .3125rem .0625rem}code,kbd{font-family:Consolas,Liberation Mono,Courier,monospace;color:#0a0a0a;background-color:#e6e6e6}kbd{padding:.125rem .25rem 0;margin:0}.subheader{margin-top:.2rem;margin-bottom:.5rem;font-weight:400;line-height:1.4;color:#8a8a8a}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}.no-bullet{margin-left:0;list-style:none}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^='#']:after,a[href^='javascript:']:after{content:''}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{display:block;box-sizing:border-box;width:100%;height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-family:inherit;font-size:1rem;color:#0a0a0a;background-color:#fefefe;box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);border-radius:0;-webkit-transition:-webkit-box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out;-webkit-appearance:none;-moz-appearance:none}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{border:1px solid #8a8a8a;background-color:#fefefe;outline:none;box-shadow:0 0 5px #cacaca;-webkit-transition:-webkit-box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out}textarea{max-width:100%}textarea[rows]{height:auto}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#cacaca}input::-moz-placeholder,textarea::-moz-placeholder{color:#cacaca}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#cacaca}input::placeholder,textarea::placeholder{color:#cacaca}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{border-radius:0;-webkit-appearance:none;-moz-appearance:none}input[type=search]{box-sizing:border-box}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-left:.5rem;margin-right:1rem;margin-bottom:0;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{display:block;margin:0;font-size:.875rem;font-weight:400;line-height:1.8;color:#0a0a0a}label.middle{margin:0 0 1rem;padding:.5625rem 0}.help-text{margin-top:-.5rem;font-size:.8125rem;font-style:italic;color:#0a0a0a}.input-group{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;margin-bottom:1rem;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.input-group>:first-child,.input-group>:last-child>*{border-radius:0 0 0 0}.input-group-button,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{text-align:center;padding:0 1rem;background:#e6e6e6;color:#0a0a0a;border:1px solid #cacaca;white-space:nowrap;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{border-radius:0;-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px;height:auto}.input-group-button{padding-top:0;padding-bottom:0;text-align:center;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.input-group-button a,.input-group-button button,.input-group-button input{margin:0}fieldset{border:0;padding:0;margin:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;padding:1.25rem;margin:1.125rem 0}.fieldset legend{background:#fefefe;padding:0 .1875rem;margin:0;margin-left:-.1875rem}select{height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-size:1rem;font-family:inherit;line-height:normal;color:#0a0a0a;background-color:#fefefe;border-radius:0;-webkit-appearance:none;-moz-appearance:none;background-image:url("data:image/svg+xml;utf8,");background-size:9px 6px;background-position:right -1rem center;background-origin:content-box;background-repeat:no-repeat;padding-right:1.5rem}@media screen and (min-width:0\0){select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==")}}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{height:auto;background-image:none}.is-invalid-input:not(:focus){background-color:rgba(236,88,64,.1);border-color:#ec5840}.form-error,.is-invalid-label{color:#ec5840}.form-error{display:none;margin-top:-.5rem;margin-bottom:1rem;font-size:.75rem;font-weight:700}.form-error.is-visible{display:block}.button{display:inline-block;text-align:center;line-height:1;cursor:pointer;-webkit-appearance:none;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle;border:1px solid transparent;border-radius:0;padding:.85em 1em;margin:0 0 1rem;font-size:.9rem;background-color:#2199e8;color:#fefefe}[data-whatinput=mouse] .button{outline:0}.button:focus,.button:hover{background-color:#1583cc;color:#fefefe}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;width:100%;margin-left:0;margin-right:0}.button.primary{background-color:#2199e8;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#147cc0;color:#fefefe}.button.secondary{background-color:#777;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5f5f5f;color:#fefefe}.button.success{background-color:#3adb76;color:#fefefe}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#fefefe}.button.warning{background-color:#ffae00;color:#fefefe}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#fefefe}.button.alert{background-color:#ec5840;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#da3116;color:#fefefe}.button.hollow{border:1px solid #2199e8;color:#2199e8}.button.hollow,.button.hollow:focus,.button.hollow:hover{background-color:transparent}.button.hollow:focus,.button.hollow:hover{border-color:#0c4d78;color:#0c4d78}.button.hollow.primary{border:1px solid #2199e8;color:#2199e8}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c4d78;color:#0c4d78}.button.hollow.secondary{border:1px solid #777;color:#777}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3c3c3c;color:#3c3c3c}.button.hollow.success{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert{border:1px solid #ec5840;color:#ec5840}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#881f0e;color:#881f0e}.button.disabled,.button[disabled]{opacity:.25;cursor:not-allowed}.button.disabled:focus,.button.disabled:hover,.button[disabled]:focus,.button[disabled]:hover{background-color:#2199e8;color:#fefefe}.button.disabled.primary,.button[disabled].primary{opacity:.25;cursor:not-allowed}.button.disabled.primary:focus,.button.disabled.primary:hover,.button[disabled].primary:focus,.button[disabled].primary:hover{background-color:#2199e8;color:#fefefe}.button.disabled.secondary,.button[disabled].secondary{opacity:.25;cursor:not-allowed}.button.disabled.secondary:focus,.button.disabled.secondary:hover,.button[disabled].secondary:focus,.button[disabled].secondary:hover{background-color:#777;color:#fefefe}.button.disabled.success,.button[disabled].success{opacity:.25;cursor:not-allowed}.button.disabled.success:focus,.button.disabled.success:hover,.button[disabled].success:focus,.button[disabled].success:hover{background-color:#3adb76;color:#fefefe}.button.disabled.warning,.button[disabled].warning{opacity:.25;cursor:not-allowed}.button.disabled.warning:focus,.button.disabled.warning:hover,.button[disabled].warning:focus,.button[disabled].warning:hover{background-color:#ffae00;color:#fefefe}.button.disabled.alert,.button[disabled].alert{opacity:.25;cursor:not-allowed}.button.disabled.alert:focus,.button.disabled.alert:hover,.button[disabled].alert:focus,.button[disabled].alert:hover{background-color:#ec5840;color:#fefefe}.button.dropdown:after{content:'';display:block;width:0;height:0;border:.4em inset;border-color:#fefefe transparent transparent;border-top-style:solid;border-bottom-width:0;position:relative;top:.4em;float:right;margin-left:1em;display:inline-block}.button.arrow-only:after{margin-left:0;float:none;top:-.1em}.accordion{list-style-type:none;background:#fefefe;margin-left:0}.accordion-item:first-child>:first-child,.accordion-item:last-child>:last-child{border-radius:0 0 0 0}.accordion-title{display:block;padding:1.25rem 1rem;line-height:1;font-size:.75rem;color:#2199e8;position:relative;border:1px solid #e6e6e6;border-bottom:0}:last-child:not(.is-active)>.accordion-title{border-radius:0 0 0 0;border-bottom:1px solid #e6e6e6}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:'+';position:absolute;right:1rem;top:50%;margin-top:-.5rem}.is-active>.accordion-title:before{content:'–'}.accordion-content{padding:1rem;display:none;border:1px solid #e6e6e6;border-bottom:0;background-color:#fefefe;color:#0a0a0a}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.is-accordion-submenu-parent>a{position:relative}.is-accordion-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:6px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;position:absolute;top:50%;margin-top:-4px;right:1rem}.is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform-origin:50% 50%;transform-origin:50% 50%;-webkit-transform:scaleY(-1);transform:scaleY(-1)}.badge{display:inline-block;padding:.3em;min-width:2.1em;font-size:.6rem;text-align:center;border-radius:50%;background:#2199e8;color:#fefefe}.badge.secondary{background:#777;color:#fefefe}.badge.success{background:#3adb76;color:#fefefe}.badge.warning{background:#ffae00;color:#fefefe}.badge.alert{background:#ec5840;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{content:' ';display:table;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{float:left;color:#0a0a0a;font-size:.6875rem;cursor:default;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;position:relative;top:1px;opacity:1}.breadcrumbs a{color:#2199e8}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.button-group{margin-bottom:1rem;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.button-group:after,.button-group:before{content:' ';display:table;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.button-group:after{clear:both}.button-group .button{margin:0;margin-right:1px;margin-bottom:1px;font-size:.9rem;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button{background-color:#2199e8;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#147cc0;color:#fefefe}.button-group.secondary .button{background-color:#777;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5f5f5f;color:#fefefe}.button-group.success .button{background-color:#3adb76;color:#fefefe}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#fefefe}.button-group.warning .button{background-color:#ffae00;color:#fefefe}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#fefefe}.button-group.alert .button{background-color:#ec5840;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#da3116;color:#fefefe}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}@media screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px;margin-bottom:0}}@media screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px;margin-bottom:0}}@media screen and (max-width:39.9375em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}.callout{margin:0 0 1rem;padding:1rem;border:1px solid hsla(0,0%,4%,.25);border-radius:0;position:relative;color:#0a0a0a;background-color:#fff}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#def0fc}.callout.secondary{background-color:#ebebeb}.callout.success{background-color:#e1faea}.callout.warning{background-color:#fff3d9}.callout.alert{background-color:#fce6e2}.callout.small{padding:.5rem}.callout.large{padding:3rem}.close-button{position:absolute;color:#8a8a8a;right:1rem;top:.5rem;font-size:2em;line-height:1;cursor:pointer}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.menu{margin:0;list-style-type:none;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-wrap:nowrap;flex-wrap:nowrap}[data-whatinput=mouse] .menu>li{outline:0}.menu>li>a{display:block;padding:.7rem 1rem;line-height:1}.menu a,.menu button,.menu input{margin-bottom:0}.menu>li>a{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row}.menu>li>a i,.menu>li>a img,.menu>li>a svg{margin-right:.25rem}.menu>li{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.menu.vertical{-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical>li{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.menu.vertical>li>a{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}@media screen and (min-width:40em){.menu.medium-horizontal{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-horizontal>li{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.menu.medium-vertical{-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical>li{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.menu.medium-vertical>li>a{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}}@media screen and (min-width:64em){.menu.large-horizontal{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-horizontal>li{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.menu.large-vertical{-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical>li{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.menu.large-vertical>li>a{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}}.menu.simple li{line-height:1;display:inline-block;margin-right:1rem}.menu.simple a{padding:0}.menu.align-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.menu.expanded>li{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded>li:first-child:last-child{width:100%}.menu.icon-top>li>a{-ms-flex-flow:column nowrap;flex-flow:column}.menu.icon-top>li>a i,.menu.icon-top>li>a img,.menu.icon-top>li>a svg{-ms-flex-item-align:stretch;align-self:stretch;text-align:center;margin-bottom:.25rem}.menu.nested{margin-left:1rem}.menu .active>a{color:#fefefe;background:#2199e8}.menu-text{font-weight:700;color:inherit;line-height:1;padding-top:0;padding-bottom:0;padding:.7rem 1rem}.menu-centered{text-align:center}.menu-centered>.menu{display:inline-block}.no-js [data-responsive-menu] ul{display:none}.menu-icon{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon:after{content:'';position:absolute;display:block;width:100%;height:2px;background:#fefefe;top:0;left:0;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe}.menu-icon:hover:after{background:#cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon.dark:after{content:'';position:absolute;display:block;width:100%;height:2px;background:#0a0a0a;top:0;left:0;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a}.menu-icon.dark:hover:after{background:#8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.is-drilldown{position:relative;overflow:hidden}.is-drilldown li{display:block!important}.is-drilldown-submenu{position:absolute;top:0;left:100%;z-index:-1;width:100%;background:#fefefe;-webkit-transition:-webkit-transform .15s linear;transition:transform .15s linear}.is-drilldown-submenu.is-active{z-index:1;display:block;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);transform:translateX(100%)}.is-drilldown-submenu-parent>a{position:relative}.is-drilldown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:6px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0;position:absolute;top:50%;margin-top:-6px;right:1rem}.js-drilldown-back>a:before{content:'';display:block;width:0;height:0;border:6px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0;display:inline-block;vertical-align:middle;margin-right:.75rem}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:block;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-open{visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;right:5px;margin-top:-2px}[data-whatinput=mouse] .dropdown.menu a{outline:0}.no-js .dropdown.menu ul{display:none}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.vertical>li>a:after{right:14px;margin-top:-3px}.dropdown.menu.vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}@media screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;right:5px;margin-top:-2px}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.medium-vertical>li>a:after{right:14px;margin-top:-3px}.dropdown.menu.medium-vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}}@media screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;right:5px;margin-top:-2px}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.large-vertical>li>a:after{right:14px;margin-top:-3px}.dropdown.menu.large-vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{top:100%;left:auto;right:0}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{position:absolute;top:50%;right:5px;margin-top:-2px}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{top:100%;left:auto}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{right:auto;left:100%}.is-dropdown-submenu{display:none;position:absolute;top:0;left:100%;min-width:200px;z-index:1;background:#fefefe;border:1px solid #cacaca}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px;margin-top:-3px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.flex-video{position:relative;height:0;padding-bottom:75%;margin-bottom:1rem;overflow:hidden}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video{position:absolute;top:0;left:0;width:100%;height:100%}.flex-video.widescreen{padding-bottom:56.25%}.flex-video.vimeo{padding-top:0}.label{display:inline-block;padding:.33333rem .5rem;font-size:.8rem;line-height:1;white-space:nowrap;cursor:default;border-radius:0;background:#2199e8;color:#fefefe}.label.secondary{background:#777;color:#fefefe}.label.success{background:#3adb76;color:#fefefe}.label.warning{background:#ffae00;color:#fefefe}.label.alert{background:#ec5840;color:#fefefe}.media-object{margin-bottom:1rem;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.media-object img{max-width:none}@media screen and (max-width:39.9375em){.media-object.stack-for-small{-ms-flex-wrap:wrap;flex-wrap:wrap}}@media screen and (max-width:39.9375em){.media-object.stack-for-small .media-object-section{padding:0;padding-bottom:1rem;-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}.media-object.stack-for-small .media-object-section img{width:100%}}.media-object-section{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}.media-object-section.main-section{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}body,html{height:100%}.off-canvas-wrapper{width:100%;overflow-x:hidden;position:relative;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-overflow-scrolling:auto}.off-canvas-wrapper-inner{position:relative;width:100%;min-height:100%;-webkit-transition:-webkit-transform .5s ease;transition:transform .5s ease}.off-canvas-wrapper-inner:after,.off-canvas-wrapper-inner:before{content:' ';display:table;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.off-canvas-wrapper-inner:after{clear:both}.off-canvas-content{min-height:100%;background:#fefefe;-webkit-transition:-webkit-transform .5s ease;transition:transform .5s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1;padding-bottom:.1px;box-shadow:0 0 10px hsla(0,0%,4%,.5)}.js-off-canvas-exit{display:none;position:absolute;top:0;left:0;width:100%;height:100%;background:hsla(0,0%,100%,.25);cursor:pointer;-webkit-transition:background .5s ease;transition:background .5s ease}.off-canvas{position:absolute;background:#e6e6e6;z-index:-1;max-height:100%;overflow-y:auto;-webkit-transform:translateX(0);transform:translateX(0)}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.position-left{left:-250px;top:0;width:250px}.is-open-left{-webkit-transform:translateX(250px);transform:translateX(250px)}.off-canvas.position-right{right:-250px;top:0;width:250px}.is-open-right{-webkit-transform:translateX(-250px);transform:translateX(-250px)}@media screen and (min-width:40em){.position-left.reveal-for-medium{left:0;z-index:auto;position:fixed}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{right:0;z-index:auto;position:fixed}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}}@media screen and (min-width:64em){.position-left.reveal-for-large{left:0;z-index:auto;position:fixed}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{right:0;z-index:auto;position:fixed}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}}.orbit,.orbit-container{position:relative}.orbit-container{margin:0;overflow:hidden;list-style:none}.orbit-slide{width:100%;max-height:100%}.orbit-slide.no-motionui.is-active{top:0;left:0}.orbit-figure{margin:0}.orbit-image{margin:0;width:100%;max-width:100%}.orbit-caption{bottom:0;width:100%;margin-bottom:0;background-color:hsla(0,0%,4%,.5)}.orbit-caption,.orbit-next,.orbit-previous{position:absolute;padding:1rem;color:#fefefe}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{position:relative;margin-top:.8rem;margin-bottom:.8rem;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{width:1.2rem;height:1.2rem;margin:.1rem;background-color:#cacaca;border-radius:50%}.orbit-bullets button.is-active,.orbit-bullets button:hover{background-color:#8a8a8a}.pagination{margin-left:0;margin-bottom:1rem}.pagination:after,.pagination:before{content:' ';display:table;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.pagination:after{clear:both}.pagination li{font-size:.875rem;margin-right:.0625rem;border-radius:0;display:none}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{color:#0a0a0a;display:block;padding:.1875rem .625rem;border-radius:0}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{padding:.1875rem .625rem;background:#2199e8;color:#fefefe;cursor:default}.pagination .disabled{padding:.1875rem .625rem;color:#cacaca;cursor:not-allowed}.pagination .disabled:hover{background:transparent}.pagination .ellipsis:after{content:'\2026';padding:.1875rem .625rem;color:#0a0a0a}.pagination-previous.disabled:before,.pagination-previous a:before{content:'\00ab';display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:'\00bb';display:inline-block;margin-left:.5rem}.progress{background-color:#cacaca;height:1rem;margin-bottom:1rem;border-radius:0}.progress.primary .progress-meter{background-color:#2199e8}.progress.secondary .progress-meter{background-color:#777}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#ec5840}.progress-meter{position:relative;display:block;width:0;height:100%;background-color:#2199e8}.progress-meter-text{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;margin:0;font-size:.75rem;font-weight:700;color:#fefefe;white-space:nowrap}.slider{position:relative;height:.5rem;margin-top:1.25rem;margin-bottom:2.25rem;background-color:#e6e6e6;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-touch-action:none;touch-action:none}.slider-fill{position:absolute;top:0;left:0;display:inline-block;max-width:100%;height:.5rem;background-color:#cacaca;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;left:0;z-index:1;display:inline-block;width:1.4rem;height:1.4rem;background-color:#2199e8;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-ms-touch-action:manipulation;touch-action:manipulation;border-radius:0}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#1583cc}.slider-handle.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{opacity:.25;cursor:not-allowed}.slider.vertical{display:inline-block;width:.5rem;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);transform:scaleY(-1)}.slider.vertical .slider-fill{top:0;width:.5rem;max-height:100%}.slider.vertical .slider-handle{position:absolute;top:0;left:50%;width:1.4rem;height:1.4rem;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.sticky-container{position:relative}.sticky{position:absolute;z-index:0;-webkit-transform:translateZ(0);transform:translateZ(0)}.sticky.is-stuck{position:fixed;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{position:absolute;left:auto;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}body.is-reveal-open{overflow:hidden}html.is-reveal-open,html.is-reveal-open body{min-height:100%;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.reveal-overlay{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:1005;background-color:hsla(0,0%,4%,.45);overflow-y:scroll}.reveal{display:none;z-index:1006;padding:1rem;border:1px solid #cacaca;background-color:#fefefe;border-radius:0;position:relative;top:100px;margin-left:auto;margin-right:auto;overflow-y:auto}[data-whatinput=mouse] .reveal{outline:0}@media screen and (min-width:40em){.reveal{min-height:0}}.reveal .column,.reveal .columns{min-width:0}.reveal>:last-child{margin-bottom:0}@media screen and (min-width:40em){.reveal{width:600px;max-width:75rem}}@media screen and (min-width:40em){.reveal .reveal{left:auto;right:auto;margin:0 auto}}.reveal.collapse{padding:0}@media screen and (min-width:40em){.reveal.tiny{width:30%;max-width:75rem}}@media screen and (min-width:40em){.reveal.small{width:50%;max-width:75rem}}@media screen and (min-width:40em){.reveal.large{width:90%;max-width:75rem}}.reveal.full{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}@media screen and (max-width:39.9375em){.reveal{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}}.reveal.without-overlay{position:fixed}.switch{height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fefefe;font-weight:700;font-size:.875rem}.switch-input{opacity:0;position:absolute;margin-bottom:0}.switch-paddle{background:#cacaca;cursor:pointer;display:block;position:relative;width:4rem;height:2rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;border-radius:0;color:inherit;font-weight:inherit}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;content:'';display:block;position:absolute;height:1.5rem;left:.25rem;top:.25rem;width:1.5rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;-webkit-transform:translateZ(0);transform:translateZ(0);border-radius:0}input:checked~.switch-paddle{background:#2199e8}input:checked~.switch-paddle:after{left:2.25rem}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{left:8%;display:none}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{width:3rem;height:1.5rem;font-size:.625rem}.switch.tiny .switch-paddle:after{width:1rem;height:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{width:3.5rem;height:1.75rem;font-size:.75rem}.switch.small .switch-paddle:after{width:1.25rem;height:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{width:5rem;height:2.5rem;font-size:1rem}.switch.large .switch-paddle:after{width:2rem;height:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{width:100%;margin-bottom:1rem;border-radius:0}table tbody,table tfoot,table thead{border:1px solid #f1f1f1;background-color:#fefefe}table caption{font-weight:700;padding:.5rem .625rem .625rem}table thead{background:#f8f8f8;color:#0a0a0a}table tfoot{background:#f1f1f1;color:#0a0a0a}table tfoot tr,table thead tr{background:transparent}table tfoot td,table tfoot th,table thead td,table thead th{padding:.5rem .625rem .625rem;font-weight:700;text-align:left}table tbody tr:nth-child(even){background-color:#f1f1f1}table tbody td,table tbody th{padding:.5rem .625rem .625rem}@media screen and (max-width:63.9375em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;width:100%;overflow-x:auto}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover tbody tr:nth-of-type(even):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.table-scroll table{width:auto}.tabs{margin:0;list-style-type:none;background:#fefefe;border:1px solid #e6e6e6}.tabs:after,.tabs:before{content:' ';display:table;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{width:auto;float:none;display:block}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:transparent}.tabs.primary{background:#2199e8}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1893e4}.tabs-title{float:left}.tabs-title>a{display:block;padding:1.25rem 1.5rem;line-height:1;font-size:.75rem}.tabs-title>a:hover{background:#fefefe}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6}.tabs-content{background:#fefefe;-webkit-transition:all .5s ease;transition:all .5s ease;border:1px solid #e6e6e6;border-top:0}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;max-width:100%;-webkit-transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;border-radius:0;margin-bottom:1rem}.thumbnail:focus,.thumbnail:hover{box-shadow:0 0 6px 1px rgba(33,153,232,.5)}.title-bar{background:#0a0a0a;color:#fefefe;padding:.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{vertical-align:middle}.has-tip,.title-bar-title{font-weight:700;display:inline-block}.has-tip{border-bottom:1px dotted #8a8a8a;position:relative;cursor:help}.tooltip{background-color:#0a0a0a;color:#fefefe;font-size:80%;padding:.75rem;position:absolute;z-index:10;top:calc(100% + .6495rem);max-width:10rem!important;border-radius:0}.tooltip:before{border:.75rem inset;border-color:transparent transparent #0a0a0a;border-bottom-style:solid;border-top-width:0;bottom:100%;position:absolute;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before,.tooltip:before{content:'';display:block;width:0;height:0}.tooltip.top:before{border:.75rem inset;border-color:#0a0a0a transparent transparent;border-top-style:solid;border-bottom-width:0;top:100%;bottom:auto}.tooltip.left:before{border:.75rem inset;border-color:transparent transparent transparent #0a0a0a;border-left-style:solid;border-right-width:0;left:100%}.tooltip.left:before,.tooltip.right:before{content:'';display:block;width:0;height:0;bottom:auto;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border:.75rem inset;border-color:transparent #0a0a0a transparent transparent;border-right-style:solid;border-left-width:0;left:auto;right:100%}.top-bar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-ms-flex-wrap:nowrap;flex-wrap:nowrap;padding:.5rem;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{max-width:200px;margin-right:1rem}.top-bar .input-group-field{width:100%;margin-right:0}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media screen and (min-width:40em){.top-bar{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.top-bar .top-bar-right{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}}@media screen and (max-width:63.9375em){.top-bar.stacked-for-medium{-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media screen and (max-width:74.9375em){.top-bar.stacked-for-large{-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin-right:1rem}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.hide{display:none!important}.invisible{visibility:hidden}@media screen and (max-width:39.9375em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.9375em){.show-for-medium{display:none!important}}@media screen and (min-width:40em) and (max-width:63.9375em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.9375em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.9375em){.show-for-large{display:none!important}}@media screen and (min-width:64em) and (max-width:74.9375em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.9375em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}.show-on-focus:active,.show-on-focus:focus{position:static!important;height:auto;width:auto;overflow:visible;clip:auto}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{content:' ';display:table;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.clearfix:after{clear:both}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;justify-content:space-around}.align-top{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;align-self:stretch}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}@media screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}}@media screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}} \ No newline at end of file diff --git a/sopds_web_backend/static/css/foundation-rtl.css b/sopds_web_backend/static/css/foundation-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..c374d7d9e70b3156ab93944df1bb3ea352315af6 --- /dev/null +++ b/sopds_web_backend/static/css/foundation-rtl.css @@ -0,0 +1,3613 @@ +@charset "UTF-8"; +/** + * Foundation for Sites by ZURB + * Version 6.2.4 + * foundation.zurb.com + * Licensed under MIT Open Source + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS and IE text size adjust after device orientation change, + * without disabling user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability of focused elements when they are also in an + * active/hover state. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: not-allowed; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome. + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -webkit-box-sizing: content-box; + box-sizing: content-box; + /* 2 */ } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + * [NOTE] We don't enable this ruleset in Foundation, because we want the
element to have plain styling. + */ +/* fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; + } */ +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +.foundation-mq { + font-family: "small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"; } + +html { + font-size: 100%; + -webkit-box-sizing: border-box; + box-sizing: border-box; } + +*, +*::before, +*::after { + -webkit-box-sizing: inherit; + box-sizing: inherit; } + +body { + padding: 0; + margin: 0; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + line-height: 1.5; + color: #0a0a0a; + background: #fefefe; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + +img { + max-width: 100%; + height: auto; + -ms-interpolation-mode: bicubic; + display: inline-block; + vertical-align: middle; } + +textarea { + height: auto; + min-height: 50px; + border-radius: 0; } + +select { + width: 100%; + border-radius: 0; } + +#map_canvas img, +#map_canvas embed, +#map_canvas object, +.map_canvas img, +.map_canvas embed, +.map_canvas object, +.mqa-display img, +.mqa-display embed, +.mqa-display object { + max-width: none !important; } + +button { + -webkit-appearance: none; + -moz-appearance: none; + background: transparent; + padding: 0; + border: 0; + border-radius: 0; + line-height: 1; } + [data-whatinput='mouse'] button { + outline: 0; } + +.is-visible { + display: block !important; } + +.is-hidden { + display: none !important; } + +.row { + max-width: 75rem; + margin-left: auto; + margin-right: auto; } + .row::before, .row::after { + content: ' '; + display: table; } + .row::after { + clear: both; } + .row.collapse > .column, .row.collapse > .columns { + padding-left: 0; + padding-right: 0; } + .row .row { + margin-left: -0.625rem; + margin-right: -0.625rem; } + @media screen and (min-width: 40em) { + .row .row { + margin-left: -0.9375rem; + margin-right: -0.9375rem; } } + .row .row.collapse { + margin-left: 0; + margin-right: 0; } + .row.expanded { + max-width: none; } + .row.expanded .row { + margin-left: auto; + margin-right: auto; } + +.column, .columns { + width: 100%; + float: right; + padding-left: 0.625rem; + padding-right: 0.625rem; } + @media screen and (min-width: 40em) { + .column, .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } } + .column:last-child:not(:first-child), .columns:last-child:not(:first-child) { + float: left; } + .column.end:last-child:last-child, .end.columns:last-child:last-child { + float: right; } + +.column.row.row, .row.row.columns { + float: none; } + +.row .column.row.row, .row .row.row.columns { + padding-left: 0; + padding-right: 0; + margin-left: 0; + margin-right: 0; } + +.small-1 { + width: 8.33333%; } + +.small-push-1 { + position: relative; + right: 8.33333%; } + +.small-pull-1 { + position: relative; + right: -8.33333%; } + +.small-offset-0 { + margin-right: 0%; } + +.small-2 { + width: 16.66667%; } + +.small-push-2 { + position: relative; + right: 16.66667%; } + +.small-pull-2 { + position: relative; + right: -16.66667%; } + +.small-offset-1 { + margin-right: 8.33333%; } + +.small-3 { + width: 25%; } + +.small-push-3 { + position: relative; + right: 25%; } + +.small-pull-3 { + position: relative; + right: -25%; } + +.small-offset-2 { + margin-right: 16.66667%; } + +.small-4 { + width: 33.33333%; } + +.small-push-4 { + position: relative; + right: 33.33333%; } + +.small-pull-4 { + position: relative; + right: -33.33333%; } + +.small-offset-3 { + margin-right: 25%; } + +.small-5 { + width: 41.66667%; } + +.small-push-5 { + position: relative; + right: 41.66667%; } + +.small-pull-5 { + position: relative; + right: -41.66667%; } + +.small-offset-4 { + margin-right: 33.33333%; } + +.small-6 { + width: 50%; } + +.small-push-6 { + position: relative; + right: 50%; } + +.small-pull-6 { + position: relative; + right: -50%; } + +.small-offset-5 { + margin-right: 41.66667%; } + +.small-7 { + width: 58.33333%; } + +.small-push-7 { + position: relative; + right: 58.33333%; } + +.small-pull-7 { + position: relative; + right: -58.33333%; } + +.small-offset-6 { + margin-right: 50%; } + +.small-8 { + width: 66.66667%; } + +.small-push-8 { + position: relative; + right: 66.66667%; } + +.small-pull-8 { + position: relative; + right: -66.66667%; } + +.small-offset-7 { + margin-right: 58.33333%; } + +.small-9 { + width: 75%; } + +.small-push-9 { + position: relative; + right: 75%; } + +.small-pull-9 { + position: relative; + right: -75%; } + +.small-offset-8 { + margin-right: 66.66667%; } + +.small-10 { + width: 83.33333%; } + +.small-push-10 { + position: relative; + right: 83.33333%; } + +.small-pull-10 { + position: relative; + right: -83.33333%; } + +.small-offset-9 { + margin-right: 75%; } + +.small-11 { + width: 91.66667%; } + +.small-push-11 { + position: relative; + right: 91.66667%; } + +.small-pull-11 { + position: relative; + right: -91.66667%; } + +.small-offset-10 { + margin-right: 83.33333%; } + +.small-12 { + width: 100%; } + +.small-offset-11 { + margin-right: 91.66667%; } + +.small-up-1 > .column, .small-up-1 > .columns { + width: 100%; + float: right; } + .small-up-1 > .column:nth-of-type(1n), .small-up-1 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-1 > .column:nth-of-type(1n+1), .small-up-1 > .columns:nth-of-type(1n+1) { + clear: both; } + .small-up-1 > .column:last-child, .small-up-1 > .columns:last-child { + float: right; } + +.small-up-2 > .column, .small-up-2 > .columns { + width: 50%; + float: right; } + .small-up-2 > .column:nth-of-type(1n), .small-up-2 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-2 > .column:nth-of-type(2n+1), .small-up-2 > .columns:nth-of-type(2n+1) { + clear: both; } + .small-up-2 > .column:last-child, .small-up-2 > .columns:last-child { + float: right; } + +.small-up-3 > .column, .small-up-3 > .columns { + width: 33.33333%; + float: right; } + .small-up-3 > .column:nth-of-type(1n), .small-up-3 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-3 > .column:nth-of-type(3n+1), .small-up-3 > .columns:nth-of-type(3n+1) { + clear: both; } + .small-up-3 > .column:last-child, .small-up-3 > .columns:last-child { + float: right; } + +.small-up-4 > .column, .small-up-4 > .columns { + width: 25%; + float: right; } + .small-up-4 > .column:nth-of-type(1n), .small-up-4 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-4 > .column:nth-of-type(4n+1), .small-up-4 > .columns:nth-of-type(4n+1) { + clear: both; } + .small-up-4 > .column:last-child, .small-up-4 > .columns:last-child { + float: right; } + +.small-up-5 > .column, .small-up-5 > .columns { + width: 20%; + float: right; } + .small-up-5 > .column:nth-of-type(1n), .small-up-5 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-5 > .column:nth-of-type(5n+1), .small-up-5 > .columns:nth-of-type(5n+1) { + clear: both; } + .small-up-5 > .column:last-child, .small-up-5 > .columns:last-child { + float: right; } + +.small-up-6 > .column, .small-up-6 > .columns { + width: 16.66667%; + float: right; } + .small-up-6 > .column:nth-of-type(1n), .small-up-6 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-6 > .column:nth-of-type(6n+1), .small-up-6 > .columns:nth-of-type(6n+1) { + clear: both; } + .small-up-6 > .column:last-child, .small-up-6 > .columns:last-child { + float: right; } + +.small-up-7 > .column, .small-up-7 > .columns { + width: 14.28571%; + float: right; } + .small-up-7 > .column:nth-of-type(1n), .small-up-7 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-7 > .column:nth-of-type(7n+1), .small-up-7 > .columns:nth-of-type(7n+1) { + clear: both; } + .small-up-7 > .column:last-child, .small-up-7 > .columns:last-child { + float: right; } + +.small-up-8 > .column, .small-up-8 > .columns { + width: 12.5%; + float: right; } + .small-up-8 > .column:nth-of-type(1n), .small-up-8 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-8 > .column:nth-of-type(8n+1), .small-up-8 > .columns:nth-of-type(8n+1) { + clear: both; } + .small-up-8 > .column:last-child, .small-up-8 > .columns:last-child { + float: right; } + +.small-collapse > .column, .small-collapse > .columns { + padding-left: 0; + padding-right: 0; } + +.small-collapse .row { + margin-left: 0; + margin-right: 0; } + +.expanded.row .small-collapse.row { + margin-left: 0; + margin-right: 0; } + +.small-uncollapse > .column, .small-uncollapse > .columns { + padding-left: 0.625rem; + padding-right: 0.625rem; } + +.small-centered { + margin-left: auto; + margin-right: auto; } + .small-centered, .small-centered:last-child:not(:first-child) { + float: none; + clear: both; } + +.small-uncentered, +.small-push-0, +.small-pull-0 { + position: static; + margin-left: 0; + margin-right: 0; + float: left; } + +@media screen and (min-width: 40em) { + .medium-1 { + width: 8.33333%; } + .medium-push-1 { + position: relative; + right: 8.33333%; } + .medium-pull-1 { + position: relative; + right: -8.33333%; } + .medium-offset-0 { + margin-right: 0%; } + .medium-2 { + width: 16.66667%; } + .medium-push-2 { + position: relative; + right: 16.66667%; } + .medium-pull-2 { + position: relative; + right: -16.66667%; } + .medium-offset-1 { + margin-right: 8.33333%; } + .medium-3 { + width: 25%; } + .medium-push-3 { + position: relative; + right: 25%; } + .medium-pull-3 { + position: relative; + right: -25%; } + .medium-offset-2 { + margin-right: 16.66667%; } + .medium-4 { + width: 33.33333%; } + .medium-push-4 { + position: relative; + right: 33.33333%; } + .medium-pull-4 { + position: relative; + right: -33.33333%; } + .medium-offset-3 { + margin-right: 25%; } + .medium-5 { + width: 41.66667%; } + .medium-push-5 { + position: relative; + right: 41.66667%; } + .medium-pull-5 { + position: relative; + right: -41.66667%; } + .medium-offset-4 { + margin-right: 33.33333%; } + .medium-6 { + width: 50%; } + .medium-push-6 { + position: relative; + right: 50%; } + .medium-pull-6 { + position: relative; + right: -50%; } + .medium-offset-5 { + margin-right: 41.66667%; } + .medium-7 { + width: 58.33333%; } + .medium-push-7 { + position: relative; + right: 58.33333%; } + .medium-pull-7 { + position: relative; + right: -58.33333%; } + .medium-offset-6 { + margin-right: 50%; } + .medium-8 { + width: 66.66667%; } + .medium-push-8 { + position: relative; + right: 66.66667%; } + .medium-pull-8 { + position: relative; + right: -66.66667%; } + .medium-offset-7 { + margin-right: 58.33333%; } + .medium-9 { + width: 75%; } + .medium-push-9 { + position: relative; + right: 75%; } + .medium-pull-9 { + position: relative; + right: -75%; } + .medium-offset-8 { + margin-right: 66.66667%; } + .medium-10 { + width: 83.33333%; } + .medium-push-10 { + position: relative; + right: 83.33333%; } + .medium-pull-10 { + position: relative; + right: -83.33333%; } + .medium-offset-9 { + margin-right: 75%; } + .medium-11 { + width: 91.66667%; } + .medium-push-11 { + position: relative; + right: 91.66667%; } + .medium-pull-11 { + position: relative; + right: -91.66667%; } + .medium-offset-10 { + margin-right: 83.33333%; } + .medium-12 { + width: 100%; } + .medium-offset-11 { + margin-right: 91.66667%; } + .medium-up-1 > .column, .medium-up-1 > .columns { + width: 100%; + float: right; } + .medium-up-1 > .column:nth-of-type(1n), .medium-up-1 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-1 > .column:nth-of-type(1n+1), .medium-up-1 > .columns:nth-of-type(1n+1) { + clear: both; } + .medium-up-1 > .column:last-child, .medium-up-1 > .columns:last-child { + float: right; } + .medium-up-2 > .column, .medium-up-2 > .columns { + width: 50%; + float: right; } + .medium-up-2 > .column:nth-of-type(1n), .medium-up-2 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-2 > .column:nth-of-type(2n+1), .medium-up-2 > .columns:nth-of-type(2n+1) { + clear: both; } + .medium-up-2 > .column:last-child, .medium-up-2 > .columns:last-child { + float: right; } + .medium-up-3 > .column, .medium-up-3 > .columns { + width: 33.33333%; + float: right; } + .medium-up-3 > .column:nth-of-type(1n), .medium-up-3 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-3 > .column:nth-of-type(3n+1), .medium-up-3 > .columns:nth-of-type(3n+1) { + clear: both; } + .medium-up-3 > .column:last-child, .medium-up-3 > .columns:last-child { + float: right; } + .medium-up-4 > .column, .medium-up-4 > .columns { + width: 25%; + float: right; } + .medium-up-4 > .column:nth-of-type(1n), .medium-up-4 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-4 > .column:nth-of-type(4n+1), .medium-up-4 > .columns:nth-of-type(4n+1) { + clear: both; } + .medium-up-4 > .column:last-child, .medium-up-4 > .columns:last-child { + float: right; } + .medium-up-5 > .column, .medium-up-5 > .columns { + width: 20%; + float: right; } + .medium-up-5 > .column:nth-of-type(1n), .medium-up-5 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-5 > .column:nth-of-type(5n+1), .medium-up-5 > .columns:nth-of-type(5n+1) { + clear: both; } + .medium-up-5 > .column:last-child, .medium-up-5 > .columns:last-child { + float: right; } + .medium-up-6 > .column, .medium-up-6 > .columns { + width: 16.66667%; + float: right; } + .medium-up-6 > .column:nth-of-type(1n), .medium-up-6 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-6 > .column:nth-of-type(6n+1), .medium-up-6 > .columns:nth-of-type(6n+1) { + clear: both; } + .medium-up-6 > .column:last-child, .medium-up-6 > .columns:last-child { + float: right; } + .medium-up-7 > .column, .medium-up-7 > .columns { + width: 14.28571%; + float: right; } + .medium-up-7 > .column:nth-of-type(1n), .medium-up-7 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-7 > .column:nth-of-type(7n+1), .medium-up-7 > .columns:nth-of-type(7n+1) { + clear: both; } + .medium-up-7 > .column:last-child, .medium-up-7 > .columns:last-child { + float: right; } + .medium-up-8 > .column, .medium-up-8 > .columns { + width: 12.5%; + float: right; } + .medium-up-8 > .column:nth-of-type(1n), .medium-up-8 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-8 > .column:nth-of-type(8n+1), .medium-up-8 > .columns:nth-of-type(8n+1) { + clear: both; } + .medium-up-8 > .column:last-child, .medium-up-8 > .columns:last-child { + float: right; } + .medium-collapse > .column, .medium-collapse > .columns { + padding-left: 0; + padding-right: 0; } + .medium-collapse .row { + margin-left: 0; + margin-right: 0; } + .expanded.row .medium-collapse.row { + margin-left: 0; + margin-right: 0; } + .medium-uncollapse > .column, .medium-uncollapse > .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } + .medium-centered { + margin-left: auto; + margin-right: auto; } + .medium-centered, .medium-centered:last-child:not(:first-child) { + float: none; + clear: both; } + .medium-uncentered, + .medium-push-0, + .medium-pull-0 { + position: static; + margin-left: 0; + margin-right: 0; + float: left; } } + +@media screen and (min-width: 64em) { + .large-1 { + width: 8.33333%; } + .large-push-1 { + position: relative; + right: 8.33333%; } + .large-pull-1 { + position: relative; + right: -8.33333%; } + .large-offset-0 { + margin-right: 0%; } + .large-2 { + width: 16.66667%; } + .large-push-2 { + position: relative; + right: 16.66667%; } + .large-pull-2 { + position: relative; + right: -16.66667%; } + .large-offset-1 { + margin-right: 8.33333%; } + .large-3 { + width: 25%; } + .large-push-3 { + position: relative; + right: 25%; } + .large-pull-3 { + position: relative; + right: -25%; } + .large-offset-2 { + margin-right: 16.66667%; } + .large-4 { + width: 33.33333%; } + .large-push-4 { + position: relative; + right: 33.33333%; } + .large-pull-4 { + position: relative; + right: -33.33333%; } + .large-offset-3 { + margin-right: 25%; } + .large-5 { + width: 41.66667%; } + .large-push-5 { + position: relative; + right: 41.66667%; } + .large-pull-5 { + position: relative; + right: -41.66667%; } + .large-offset-4 { + margin-right: 33.33333%; } + .large-6 { + width: 50%; } + .large-push-6 { + position: relative; + right: 50%; } + .large-pull-6 { + position: relative; + right: -50%; } + .large-offset-5 { + margin-right: 41.66667%; } + .large-7 { + width: 58.33333%; } + .large-push-7 { + position: relative; + right: 58.33333%; } + .large-pull-7 { + position: relative; + right: -58.33333%; } + .large-offset-6 { + margin-right: 50%; } + .large-8 { + width: 66.66667%; } + .large-push-8 { + position: relative; + right: 66.66667%; } + .large-pull-8 { + position: relative; + right: -66.66667%; } + .large-offset-7 { + margin-right: 58.33333%; } + .large-9 { + width: 75%; } + .large-push-9 { + position: relative; + right: 75%; } + .large-pull-9 { + position: relative; + right: -75%; } + .large-offset-8 { + margin-right: 66.66667%; } + .large-10 { + width: 83.33333%; } + .large-push-10 { + position: relative; + right: 83.33333%; } + .large-pull-10 { + position: relative; + right: -83.33333%; } + .large-offset-9 { + margin-right: 75%; } + .large-11 { + width: 91.66667%; } + .large-push-11 { + position: relative; + right: 91.66667%; } + .large-pull-11 { + position: relative; + right: -91.66667%; } + .large-offset-10 { + margin-right: 83.33333%; } + .large-12 { + width: 100%; } + .large-offset-11 { + margin-right: 91.66667%; } + .large-up-1 > .column, .large-up-1 > .columns { + width: 100%; + float: right; } + .large-up-1 > .column:nth-of-type(1n), .large-up-1 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-1 > .column:nth-of-type(1n+1), .large-up-1 > .columns:nth-of-type(1n+1) { + clear: both; } + .large-up-1 > .column:last-child, .large-up-1 > .columns:last-child { + float: right; } + .large-up-2 > .column, .large-up-2 > .columns { + width: 50%; + float: right; } + .large-up-2 > .column:nth-of-type(1n), .large-up-2 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-2 > .column:nth-of-type(2n+1), .large-up-2 > .columns:nth-of-type(2n+1) { + clear: both; } + .large-up-2 > .column:last-child, .large-up-2 > .columns:last-child { + float: right; } + .large-up-3 > .column, .large-up-3 > .columns { + width: 33.33333%; + float: right; } + .large-up-3 > .column:nth-of-type(1n), .large-up-3 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-3 > .column:nth-of-type(3n+1), .large-up-3 > .columns:nth-of-type(3n+1) { + clear: both; } + .large-up-3 > .column:last-child, .large-up-3 > .columns:last-child { + float: right; } + .large-up-4 > .column, .large-up-4 > .columns { + width: 25%; + float: right; } + .large-up-4 > .column:nth-of-type(1n), .large-up-4 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-4 > .column:nth-of-type(4n+1), .large-up-4 > .columns:nth-of-type(4n+1) { + clear: both; } + .large-up-4 > .column:last-child, .large-up-4 > .columns:last-child { + float: right; } + .large-up-5 > .column, .large-up-5 > .columns { + width: 20%; + float: right; } + .large-up-5 > .column:nth-of-type(1n), .large-up-5 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-5 > .column:nth-of-type(5n+1), .large-up-5 > .columns:nth-of-type(5n+1) { + clear: both; } + .large-up-5 > .column:last-child, .large-up-5 > .columns:last-child { + float: right; } + .large-up-6 > .column, .large-up-6 > .columns { + width: 16.66667%; + float: right; } + .large-up-6 > .column:nth-of-type(1n), .large-up-6 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-6 > .column:nth-of-type(6n+1), .large-up-6 > .columns:nth-of-type(6n+1) { + clear: both; } + .large-up-6 > .column:last-child, .large-up-6 > .columns:last-child { + float: right; } + .large-up-7 > .column, .large-up-7 > .columns { + width: 14.28571%; + float: right; } + .large-up-7 > .column:nth-of-type(1n), .large-up-7 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-7 > .column:nth-of-type(7n+1), .large-up-7 > .columns:nth-of-type(7n+1) { + clear: both; } + .large-up-7 > .column:last-child, .large-up-7 > .columns:last-child { + float: right; } + .large-up-8 > .column, .large-up-8 > .columns { + width: 12.5%; + float: right; } + .large-up-8 > .column:nth-of-type(1n), .large-up-8 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-8 > .column:nth-of-type(8n+1), .large-up-8 > .columns:nth-of-type(8n+1) { + clear: both; } + .large-up-8 > .column:last-child, .large-up-8 > .columns:last-child { + float: right; } + .large-collapse > .column, .large-collapse > .columns { + padding-left: 0; + padding-right: 0; } + .large-collapse .row { + margin-left: 0; + margin-right: 0; } + .expanded.row .large-collapse.row { + margin-left: 0; + margin-right: 0; } + .large-uncollapse > .column, .large-uncollapse > .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } + .large-centered { + margin-left: auto; + margin-right: auto; } + .large-centered, .large-centered:last-child:not(:first-child) { + float: none; + clear: both; } + .large-uncentered, + .large-push-0, + .large-pull-0 { + position: static; + margin-left: 0; + margin-right: 0; + float: left; } } + +div, +dl, +dt, +dd, +ul, +ol, +li, +h1, +h2, +h3, +h4, +h5, +h6, +pre, +form, +p, +blockquote, +th, +td { + margin: 0; + padding: 0; } + +p { + font-size: inherit; + line-height: 1.6; + margin-bottom: 1rem; + text-rendering: optimizeLegibility; } + +em, +i { + font-style: italic; + line-height: inherit; } + +strong, +b { + font-weight: bold; + line-height: inherit; } + +small { + font-size: 80%; + line-height: inherit; } + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + font-style: normal; + color: inherit; + text-rendering: optimizeLegibility; + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.4; } + h1 small, + h2 small, + h3 small, + h4 small, + h5 small, + h6 small { + color: #cacaca; + line-height: 0; } + +h1 { + font-size: 1.5rem; } + +h2 { + font-size: 1.25rem; } + +h3 { + font-size: 1.1875rem; } + +h4 { + font-size: 1.125rem; } + +h5 { + font-size: 1.0625rem; } + +h6 { + font-size: 1rem; } + +@media screen and (min-width: 40em) { + h1 { + font-size: 3rem; } + h2 { + font-size: 2.5rem; } + h3 { + font-size: 1.9375rem; } + h4 { + font-size: 1.5625rem; } + h5 { + font-size: 1.25rem; } + h6 { + font-size: 1rem; } } + +a { + color: #2199e8; + text-decoration: none; + line-height: inherit; + cursor: pointer; } + a:hover, a:focus { + color: #1585cf; } + a img { + border: 0; } + +hr { + max-width: 75rem; + height: 0; + border-right: 0; + border-top: 0; + border-bottom: 1px solid #cacaca; + border-left: 0; + margin: 1.25rem auto; + clear: both; } + +ul, +ol, +dl { + line-height: 1.6; + margin-bottom: 1rem; + list-style-position: outside; } + +li { + font-size: inherit; } + +ul { + list-style-type: disc; + margin-right: 1.25rem; } + +ol { + margin-right: 1.25rem; } + +ul ul, ol ul, ul ol, ol ol { + margin-right: 1.25rem; + margin-bottom: 0; } + +dl { + margin-bottom: 1rem; } + dl dt { + margin-bottom: 0.3rem; + font-weight: bold; } + +blockquote { + margin: 0 0 1rem; + padding: 0.5625rem 1.25rem 0 1.1875rem; + border-right: 1px solid #cacaca; } + blockquote, blockquote p { + line-height: 1.6; + color: #8a8a8a; } + +cite { + display: block; + font-size: 0.8125rem; + color: #8a8a8a; } + cite:before { + content: '\2014 \0020'; } + +abbr { + color: #0a0a0a; + cursor: help; + border-bottom: 1px dotted #0a0a0a; } + +code { + font-family: Consolas, "Liberation Mono", Courier, monospace; + font-weight: normal; + color: #0a0a0a; + background-color: #e6e6e6; + border: 1px solid #cacaca; + padding: 0.125rem 0.3125rem 0.0625rem; } + +kbd { + padding: 0.125rem 0.25rem 0; + margin: 0; + background-color: #e6e6e6; + color: #0a0a0a; + font-family: Consolas, "Liberation Mono", Courier, monospace; } + +.subheader { + margin-top: 0.2rem; + margin-bottom: 0.5rem; + font-weight: normal; + line-height: 1.4; + color: #8a8a8a; } + +.lead { + font-size: 125%; + line-height: 1.6; } + +.stat { + font-size: 2.5rem; + line-height: 1; } + p + .stat { + margin-top: -1rem; } + +.no-bullet { + margin-right: 0; + list-style: none; } + +.text-left { + text-align: left; } + +.text-right { + text-align: right; } + +.text-center { + text-align: center; } + +.text-justify { + text-align: justify; } + +@media screen and (min-width: 40em) { + .medium-text-left { + text-align: left; } + .medium-text-right { + text-align: right; } + .medium-text-center { + text-align: center; } + .medium-text-justify { + text-align: justify; } } + +@media screen and (min-width: 64em) { + .large-text-left { + text-align: left; } + .large-text-right { + text-align: right; } + .large-text-center { + text-align: center; } + .large-text-justify { + text-align: justify; } } + +.show-for-print { + display: none !important; } + +@media print { + * { + background: transparent !important; + color: black !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; } + .show-for-print { + display: block !important; } + .hide-for-print { + display: none !important; } + table.show-for-print { + display: table !important; } + thead.show-for-print { + display: table-header-group !important; } + tbody.show-for-print { + display: table-row-group !important; } + tr.show-for-print { + display: table-row !important; } + td.show-for-print { + display: table-cell !important; } + th.show-for-print { + display: table-cell !important; } + a, + a:visited { + text-decoration: underline; } + a[href]:after { + content: " (" attr(href) ")"; } + .ir a:after, + a[href^='javascript:']:after, + a[href^='#']:after { + content: ''; } + abbr[title]:after { + content: " (" attr(title) ")"; } + pre, + blockquote { + border: 1px solid #8a8a8a; + page-break-inside: avoid; } + thead { + display: table-header-group; } + tr, + img { + page-break-inside: avoid; } + img { + max-width: 100% !important; } + @page { + margin: 0.5cm; } + p, + h2, + h3 { + orphans: 3; + widows: 3; } + h2, + h3 { + page-break-after: avoid; } } + +[type='text'], [type='password'], [type='date'], [type='datetime'], [type='datetime-local'], [type='month'], [type='week'], [type='email'], [type='number'], [type='search'], [type='tel'], [type='time'], [type='url'], [type='color'], +textarea { + display: block; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 2.4375rem; + padding: 0.5rem; + border: 1px solid #cacaca; + margin: 0 0 1rem; + font-family: inherit; + font-size: 1rem; + color: #0a0a0a; + background-color: #fefefe; + -webkit-box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + border-radius: 0; + -webkit-transition: -webkit-box-shadow 0.5s, border-color 0.25s ease-in-out; + transition: box-shadow 0.5s, border-color 0.25s ease-in-out; + -webkit-appearance: none; + -moz-appearance: none; } + [type='text']:focus, [type='password']:focus, [type='date']:focus, [type='datetime']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='week']:focus, [type='email']:focus, [type='number']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='url']:focus, [type='color']:focus, + textarea:focus { + border: 1px solid #8a8a8a; + background-color: #fefefe; + outline: none; + -webkit-box-shadow: 0 0 5px #cacaca; + box-shadow: 0 0 5px #cacaca; + -webkit-transition: -webkit-box-shadow 0.5s, border-color 0.25s ease-in-out; + transition: box-shadow 0.5s, border-color 0.25s ease-in-out; } + +textarea { + max-width: 100%; } + textarea[rows] { + height: auto; } + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #cacaca; } + +input::-moz-placeholder, +textarea::-moz-placeholder { + color: #cacaca; } + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #cacaca; } + +input::placeholder, +textarea::placeholder { + color: #cacaca; } + +input:disabled, input[readonly], +textarea:disabled, +textarea[readonly] { + background-color: #e6e6e6; + cursor: not-allowed; } + +[type='submit'], +[type='button'] { + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; } + +input[type='search'] { + -webkit-box-sizing: border-box; + box-sizing: border-box; } + +[type='file'], +[type='checkbox'], +[type='radio'] { + margin: 0 0 1rem; } + +[type='checkbox'] + label, +[type='radio'] + label { + display: inline-block; + margin-right: 0.5rem; + margin-left: 1rem; + margin-bottom: 0; + vertical-align: baseline; } + [type='checkbox'] + label[for], + [type='radio'] + label[for] { + cursor: pointer; } + +label > [type='checkbox'], +label > [type='radio'] { + margin-left: 0.5rem; } + +[type='file'] { + width: 100%; } + +label { + display: block; + margin: 0; + font-size: 0.875rem; + font-weight: normal; + line-height: 1.8; + color: #0a0a0a; } + label.middle { + margin: 0 0 1rem; + padding: 0.5625rem 0; } + +.help-text { + margin-top: -0.5rem; + font-size: 0.8125rem; + font-style: italic; + color: #0a0a0a; } + +.input-group { + display: table; + width: 100%; + margin-bottom: 1rem; } + .input-group > :first-child { + border-radius: 0 0 0 0; } + .input-group > :last-child > * { + border-radius: 0 0 0 0; } + +.input-group-label, .input-group-field, .input-group-button { + margin: 0; + white-space: nowrap; + display: table-cell; + vertical-align: middle; } + +.input-group-label { + text-align: center; + padding: 0 1rem; + background: #e6e6e6; + color: #0a0a0a; + border: 1px solid #cacaca; + white-space: nowrap; + width: 1%; + height: 100%; } + .input-group-label:first-child { + border-left: 0; } + .input-group-label:last-child { + border-right: 0; } + +.input-group-field { + border-radius: 0; + height: 2.5rem; } + +.input-group-button { + padding-top: 0; + padding-bottom: 0; + text-align: center; + height: 100%; + width: 1%; } + .input-group-button a, + .input-group-button input, + .input-group-button button { + margin: 0; } + +.input-group .input-group-button { + display: table-cell; } + +fieldset { + border: 0; + padding: 0; + margin: 0; } + +legend { + margin-bottom: 0.5rem; + max-width: 100%; } + +.fieldset { + border: 1px solid #cacaca; + padding: 1.25rem; + margin: 1.125rem 0; } + .fieldset legend { + background: #fefefe; + padding: 0 0.1875rem; + margin: 0; + margin-right: -0.1875rem; } + +select { + height: 2.4375rem; + padding: 0.5rem; + border: 1px solid #cacaca; + margin: 0 0 1rem; + font-size: 1rem; + font-family: inherit; + line-height: normal; + color: #0a0a0a; + background-color: #fefefe; + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + -webkit-background-size: 9px 6px; + background-size: 9px 6px; + background-position: left -1rem center; + -webkit-background-origin: content-box; + background-origin: content-box; + background-repeat: no-repeat; + padding-left: 1.5rem; } + @media screen and (min-width: 0\0) { + select { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg=="); } } + select:disabled { + background-color: #e6e6e6; + cursor: not-allowed; } + select::-ms-expand { + display: none; } + select[multiple] { + height: auto; + background-image: none; } + +.is-invalid-input:not(:focus) { + background-color: rgba(236, 88, 64, 0.1); + border-color: #ec5840; } + +.is-invalid-label { + color: #ec5840; } + +.form-error { + display: none; + margin-top: -0.5rem; + margin-bottom: 1rem; + font-size: 0.75rem; + font-weight: bold; + color: #ec5840; } + .form-error.is-visible { + display: block; } + +.button { + display: inline-block; + text-align: center; + line-height: 1; + cursor: pointer; + -webkit-appearance: none; + -webkit-transition: background-color 0.25s ease-out, color 0.25s ease-out; + transition: background-color 0.25s ease-out, color 0.25s ease-out; + vertical-align: middle; + border: 1px solid transparent; + border-radius: 0; + padding: 0.85em 1em; + margin: 0 0 1rem 0; + font-size: 0.9rem; + background-color: #2199e8; + color: #fefefe; } + [data-whatinput='mouse'] .button { + outline: 0; } + .button:hover, .button:focus { + background-color: #1583cc; + color: #fefefe; } + .button.tiny { + font-size: 0.6rem; } + .button.small { + font-size: 0.75rem; } + .button.large { + font-size: 1.25rem; } + .button.expanded { + display: block; + width: 100%; + margin-left: 0; + margin-right: 0; } + .button.primary { + background-color: #2199e8; + color: #fefefe; } + .button.primary:hover, .button.primary:focus { + background-color: #147cc0; + color: #fefefe; } + .button.secondary { + background-color: #777; + color: #fefefe; } + .button.secondary:hover, .button.secondary:focus { + background-color: #5f5f5f; + color: #fefefe; } + .button.success { + background-color: #3adb76; + color: #fefefe; } + .button.success:hover, .button.success:focus { + background-color: #22bb5b; + color: #fefefe; } + .button.warning { + background-color: #ffae00; + color: #fefefe; } + .button.warning:hover, .button.warning:focus { + background-color: #cc8b00; + color: #fefefe; } + .button.alert { + background-color: #ec5840; + color: #fefefe; } + .button.alert:hover, .button.alert:focus { + background-color: #da3116; + color: #fefefe; } + .button.hollow { + border: 1px solid #2199e8; + color: #2199e8; } + .button.hollow, .button.hollow:hover, .button.hollow:focus { + background-color: transparent; } + .button.hollow:hover, .button.hollow:focus { + border-color: #0c4d78; + color: #0c4d78; } + .button.hollow.primary { + border: 1px solid #2199e8; + color: #2199e8; } + .button.hollow.primary:hover, .button.hollow.primary:focus { + border-color: #0c4d78; + color: #0c4d78; } + .button.hollow.secondary { + border: 1px solid #777; + color: #777; } + .button.hollow.secondary:hover, .button.hollow.secondary:focus { + border-color: #3c3c3c; + color: #3c3c3c; } + .button.hollow.success { + border: 1px solid #3adb76; + color: #3adb76; } + .button.hollow.success:hover, .button.hollow.success:focus { + border-color: #157539; + color: #157539; } + .button.hollow.warning { + border: 1px solid #ffae00; + color: #ffae00; } + .button.hollow.warning:hover, .button.hollow.warning:focus { + border-color: #805700; + color: #805700; } + .button.hollow.alert { + border: 1px solid #ec5840; + color: #ec5840; } + .button.hollow.alert:hover, .button.hollow.alert:focus { + border-color: #881f0e; + color: #881f0e; } + .button.disabled, .button[disabled] { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus { + background-color: #2199e8; + color: #fefefe; } + .button.disabled.primary, .button[disabled].primary { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.primary:hover, .button.disabled.primary:focus, .button[disabled].primary:hover, .button[disabled].primary:focus { + background-color: #2199e8; + color: #fefefe; } + .button.disabled.secondary, .button[disabled].secondary { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus { + background-color: #777; + color: #fefefe; } + .button.disabled.success, .button[disabled].success { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus { + background-color: #3adb76; + color: #fefefe; } + .button.disabled.warning, .button[disabled].warning { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.warning:hover, .button.disabled.warning:focus, .button[disabled].warning:hover, .button[disabled].warning:focus { + background-color: #ffae00; + color: #fefefe; } + .button.disabled.alert, .button[disabled].alert { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus { + background-color: #ec5840; + color: #fefefe; } + .button.dropdown::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.4em; + border-color: #fefefe transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + position: relative; + top: 0.4em; + float: left; + margin-right: 1em; + display: inline-block; } + .button.arrow-only::after { + margin-right: 0; + float: none; + top: -0.1em; } + +.accordion { + list-style-type: none; + background: #fefefe; + margin-right: 0; } + +.accordion-item:first-child > :first-child { + border-radius: 0 0 0 0; } + +.accordion-item:last-child > :last-child { + border-radius: 0 0 0 0; } + +.accordion-title { + display: block; + padding: 1.25rem 1rem; + line-height: 1; + font-size: 0.75rem; + color: #2199e8; + position: relative; + border: 1px solid #e6e6e6; + border-bottom: 0; } + :last-child:not(.is-active) > .accordion-title { + border-radius: 0 0 0 0; + border-bottom: 1px solid #e6e6e6; } + .accordion-title:hover, .accordion-title:focus { + background-color: #e6e6e6; } + .accordion-title::before { + content: '+'; + position: absolute; + left: 1rem; + top: 50%; + margin-top: -0.5rem; } + .is-active > .accordion-title::before { + content: '–'; } + +.accordion-content { + padding: 1rem; + display: none; + border: 1px solid #e6e6e6; + border-bottom: 0; + background-color: #fefefe; + color: #0a0a0a; } + :last-child > .accordion-content:last-child { + border-bottom: 1px solid #e6e6e6; } + +.is-accordion-submenu-parent > a { + position: relative; } + .is-accordion-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + position: absolute; + top: 50%; + margin-top: -4px; + right: 1rem; } + +.is-accordion-submenu-parent[aria-expanded='true'] > a::after { + -webkit-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + -webkit-transform: scaleY(-1); + -ms-transform: scaleY(-1); + transform: scaleY(-1); } + +.badge { + display: inline-block; + padding: 0.3em; + min-width: 2.1em; + font-size: 0.6rem; + text-align: center; + border-radius: 50%; + background: #2199e8; + color: #fefefe; } + .badge.secondary { + background: #777; + color: #fefefe; } + .badge.success { + background: #3adb76; + color: #fefefe; } + .badge.warning { + background: #ffae00; + color: #fefefe; } + .badge.alert { + background: #ec5840; + color: #fefefe; } + +.breadcrumbs { + list-style: none; + margin: 0 0 1rem 0; } + .breadcrumbs::before, .breadcrumbs::after { + content: ' '; + display: table; } + .breadcrumbs::after { + clear: both; } + .breadcrumbs li { + float: right; + color: #0a0a0a; + font-size: 0.6875rem; + cursor: default; + text-transform: uppercase; } + .breadcrumbs li:not(:last-child)::after { + color: #cacaca; + content: "\\"; + margin: 0 0.75rem; + position: relative; + top: 1px; + opacity: 1; } + .breadcrumbs a { + color: #2199e8; } + .breadcrumbs a:hover { + text-decoration: underline; } + .breadcrumbs .disabled { + color: #cacaca; + cursor: not-allowed; } + +.button-group { + margin-bottom: 1rem; + font-size: 0; } + .button-group::before, .button-group::after { + content: ' '; + display: table; } + .button-group::after { + clear: both; } + .button-group .button { + margin: 0; + margin-left: 1px; + margin-bottom: 1px; + font-size: 0.9rem; } + .button-group .button:last-child { + margin-left: 0; } + .button-group.tiny .button { + font-size: 0.6rem; } + .button-group.small .button { + font-size: 0.75rem; } + .button-group.large .button { + font-size: 1.25rem; } + .button-group.expanded { + margin-left: -1px; } + .button-group.expanded::before, .button-group.expanded::after { + display: none; } + .button-group.expanded .button:first-child:nth-last-child(2), .button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button { + display: inline-block; + width: calc(50% - 1px); + margin-left: 1px; } + .button-group.expanded .button:first-child:nth-last-child(2):last-child, .button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button:last-child { + margin-left: -6px; } + .button-group.expanded .button:first-child:nth-last-child(3), .button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button { + display: inline-block; + width: calc(33.33333% - 1px); + margin-left: 1px; } + .button-group.expanded .button:first-child:nth-last-child(3):last-child, .button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button:last-child { + margin-left: -6px; } + .button-group.expanded .button:first-child:nth-last-child(4), .button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button { + display: inline-block; + width: calc(25% - 1px); + margin-left: 1px; } + .button-group.expanded .button:first-child:nth-last-child(4):last-child, .button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button:last-child { + margin-left: -6px; } + .button-group.expanded .button:first-child:nth-last-child(5), .button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button { + display: inline-block; + width: calc(20% - 1px); + margin-left: 1px; } + .button-group.expanded .button:first-child:nth-last-child(5):last-child, .button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button:last-child { + margin-left: -6px; } + .button-group.expanded .button:first-child:nth-last-child(6), .button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button { + display: inline-block; + width: calc(16.66667% - 1px); + margin-left: 1px; } + .button-group.expanded .button:first-child:nth-last-child(6):last-child, .button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button:last-child { + margin-left: -6px; } + .button-group.primary .button { + background-color: #2199e8; + color: #fefefe; } + .button-group.primary .button:hover, .button-group.primary .button:focus { + background-color: #147cc0; + color: #fefefe; } + .button-group.secondary .button { + background-color: #777; + color: #fefefe; } + .button-group.secondary .button:hover, .button-group.secondary .button:focus { + background-color: #5f5f5f; + color: #fefefe; } + .button-group.success .button { + background-color: #3adb76; + color: #fefefe; } + .button-group.success .button:hover, .button-group.success .button:focus { + background-color: #22bb5b; + color: #fefefe; } + .button-group.warning .button { + background-color: #ffae00; + color: #fefefe; } + .button-group.warning .button:hover, .button-group.warning .button:focus { + background-color: #cc8b00; + color: #fefefe; } + .button-group.alert .button { + background-color: #ec5840; + color: #fefefe; } + .button-group.alert .button:hover, .button-group.alert .button:focus { + background-color: #da3116; + color: #fefefe; } + .button-group.stacked .button, .button-group.stacked-for-small .button, .button-group.stacked-for-medium .button { + width: 100%; } + .button-group.stacked .button:last-child, .button-group.stacked-for-small .button:last-child, .button-group.stacked-for-medium .button:last-child { + margin-bottom: 0; } + @media screen and (min-width: 40em) { + .button-group.stacked-for-small .button { + width: auto; + margin-bottom: 0; } } + @media screen and (min-width: 64em) { + .button-group.stacked-for-medium .button { + width: auto; + margin-bottom: 0; } } + @media screen and (max-width: 39.9375em) { + .button-group.stacked-for-small.expanded { + display: block; } + .button-group.stacked-for-small.expanded .button { + display: block; + margin-left: 0; } } + +.callout { + margin: 0 0 1rem 0; + padding: 1rem; + border: 1px solid rgba(10, 10, 10, 0.25); + border-radius: 0; + position: relative; + color: #0a0a0a; + background-color: white; } + .callout > :first-child { + margin-top: 0; } + .callout > :last-child { + margin-bottom: 0; } + .callout.primary { + background-color: #def0fc; } + .callout.secondary { + background-color: #ebebeb; } + .callout.success { + background-color: #e1faea; } + .callout.warning { + background-color: #fff3d9; } + .callout.alert { + background-color: #fce6e2; } + .callout.small { + padding-top: 0.5rem; + padding-right: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.5rem; } + .callout.large { + padding-top: 3rem; + padding-right: 3rem; + padding-bottom: 3rem; + padding-left: 3rem; } + +.close-button { + position: absolute; + color: #8a8a8a; + right: 1rem; + top: 0.5rem; + font-size: 2em; + line-height: 1; + cursor: pointer; } + [data-whatinput='mouse'] .close-button { + outline: 0; } + .close-button:hover, .close-button:focus { + color: #0a0a0a; } + +.menu { + margin: 0; + list-style-type: none; } + .menu > li { + display: table-cell; + vertical-align: middle; } + [data-whatinput='mouse'] .menu > li { + outline: 0; } + .menu > li > a { + display: block; + padding: 0.7rem 1rem; + line-height: 1; } + .menu input, + .menu a, + .menu button { + margin-bottom: 0; } + .menu > li > a img, + .menu > li > a i, + .menu > li > a svg { + vertical-align: middle; } + .menu > li > a img + span, + .menu > li > a i + span, + .menu > li > a svg + span { + vertical-align: middle; } + .menu > li > a img, + .menu > li > a i, + .menu > li > a svg { + margin-left: 0.25rem; + display: inline-block; } + .menu > li { + display: table-cell; } + .menu.vertical > li { + display: block; } + @media screen and (min-width: 40em) { + .menu.medium-horizontal > li { + display: table-cell; } + .menu.medium-vertical > li { + display: block; } } + @media screen and (min-width: 64em) { + .menu.large-horizontal > li { + display: table-cell; } + .menu.large-vertical > li { + display: block; } } + .menu.simple li { + line-height: 1; + display: inline-block; + margin-left: 1rem; } + .menu.simple a { + padding: 0; } + .menu.align-left::before, .menu.align-left::after { + content: ' '; + display: table; } + .menu.align-left::after { + clear: both; } + .menu.align-left > li { + float: left; } + .menu.expanded { + width: 100%; + display: table; + table-layout: fixed; } + .menu.expanded > li:first-child:last-child { + width: 100%; } + .menu.icon-top > li > a { + text-align: center; } + .menu.icon-top > li > a img, + .menu.icon-top > li > a i, + .menu.icon-top > li > a svg { + display: block; + margin: 0 auto 0.25rem; } + .menu.nested { + margin-right: 1rem; } + .menu .active > a { + color: #fefefe; + background: #2199e8; } + +.menu-text { + font-weight: bold; + color: inherit; + line-height: 1; + padding-top: 0; + padding-bottom: 0; + padding: 0.7rem 1rem; } + +.menu-centered { + text-align: center; } + .menu-centered > .menu { + display: inline-block; } + +.no-js [data-responsive-menu] ul { + display: none; } + +.menu-icon { + position: relative; + display: inline-block; + vertical-align: middle; + cursor: pointer; + width: 20px; + height: 16px; } + .menu-icon::after { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 2px; + background: #fefefe; + top: 0; + left: 0; + -webkit-box-shadow: 0 7px 0 #fefefe, 0 14px 0 #fefefe; + box-shadow: 0 7px 0 #fefefe, 0 14px 0 #fefefe; } + .menu-icon:hover::after { + background: #cacaca; + -webkit-box-shadow: 0 7px 0 #cacaca, 0 14px 0 #cacaca; + box-shadow: 0 7px 0 #cacaca, 0 14px 0 #cacaca; } + +.menu-icon.dark { + position: relative; + display: inline-block; + vertical-align: middle; + cursor: pointer; + width: 20px; + height: 16px; } + .menu-icon.dark::after { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 2px; + background: #0a0a0a; + top: 0; + left: 0; + -webkit-box-shadow: 0 7px 0 #0a0a0a, 0 14px 0 #0a0a0a; + box-shadow: 0 7px 0 #0a0a0a, 0 14px 0 #0a0a0a; } + .menu-icon.dark:hover::after { + background: #8a8a8a; + -webkit-box-shadow: 0 7px 0 #8a8a8a, 0 14px 0 #8a8a8a; + box-shadow: 0 7px 0 #8a8a8a, 0 14px 0 #8a8a8a; } + +.is-drilldown { + position: relative; + overflow: hidden; } + .is-drilldown li { + display: block !important; } + +.is-drilldown-submenu { + position: absolute; + top: 0; + right: 100%; + z-index: -1; + width: 100%; + background: #fefefe; + -webkit-transition: -webkit-transform 0.15s linear; + transition: transform 0.15s linear; } + .is-drilldown-submenu.is-active { + z-index: 1; + display: block; + -webkit-transform: translateX(100%); + -ms-transform: translateX(100%); + transform: translateX(100%); } + .is-drilldown-submenu.is-closing { + -webkit-transform: translateX(-100%); + -ms-transform: translateX(-100%); + transform: translateX(-100%); } + +.is-drilldown-submenu-parent > a { + position: relative; } + .is-drilldown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; + position: absolute; + top: 50%; + margin-top: -6px; + left: 1rem; } + +.js-drilldown-back > a::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; + border-right-width: 0; + display: inline-block; + vertical-align: middle; + margin-left: 0.75rem; } + +.dropdown-pane { + background-color: #fefefe; + border: 1px solid #cacaca; + border-radius: 0; + display: block; + font-size: 1rem; + padding: 1rem; + position: absolute; + visibility: hidden; + width: 300px; + z-index: 10; } + .dropdown-pane.is-open { + visibility: visible; } + +.dropdown-pane.tiny { + width: 100px; } + +.dropdown-pane.small { + width: 200px; } + +.dropdown-pane.large { + width: 400px; } + +.dropdown.menu > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + +.dropdown.menu > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + +.dropdown.menu > li.is-dropdown-submenu-parent > a { + padding-left: 1.5rem; + position: relative; } + +.dropdown.menu > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + left: 5px; + margin-top: -2px; } + +[data-whatinput='mouse'] .dropdown.menu a { + outline: 0; } + +.no-js .dropdown.menu ul { + display: none; } + +.dropdown.menu.vertical > li .is-dropdown-submenu { + top: 0; } + +.dropdown.menu.vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + +.dropdown.menu.vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + +.dropdown.menu.vertical > li > a::after { + left: 14px; + margin-top: -3px; } + +.dropdown.menu.vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + +.dropdown.menu.vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } + +@media screen and (min-width: 40em) { + .dropdown.menu.medium-horizontal > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + .dropdown.menu.medium-horizontal > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a { + padding-left: 1.5rem; + position: relative; } + .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + left: 5px; + margin-top: -2px; } + .dropdown.menu.medium-vertical > li .is-dropdown-submenu { + top: 0; } + .dropdown.menu.medium-vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .dropdown.menu.medium-vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + .dropdown.menu.medium-vertical > li > a::after { + left: 14px; + margin-top: -3px; } + .dropdown.menu.medium-vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .dropdown.menu.medium-vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } } + +@media screen and (min-width: 64em) { + .dropdown.menu.large-horizontal > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + .dropdown.menu.large-horizontal > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a { + padding-left: 1.5rem; + position: relative; } + .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + left: 5px; + margin-top: -2px; } + .dropdown.menu.large-vertical > li .is-dropdown-submenu { + top: 0; } + .dropdown.menu.large-vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .dropdown.menu.large-vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + .dropdown.menu.large-vertical > li > a::after { + left: 14px; + margin-top: -3px; } + .dropdown.menu.large-vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .dropdown.menu.large-vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } } + +.dropdown.menu.align-right .is-dropdown-submenu.first-sub { + top: 100%; + left: auto; + right: 0; } + +.is-dropdown-menu.vertical { + width: 100px; } + .is-dropdown-menu.vertical.align-right { + float: right; } + +.is-dropdown-submenu-parent { + position: relative; } + .is-dropdown-submenu-parent a::after { + position: absolute; + top: 50%; + left: 5px; + margin-top: -2px; } + .is-dropdown-submenu-parent.opens-inner > .is-dropdown-submenu { + top: 100%; + right: auto; } + .is-dropdown-submenu-parent.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .is-dropdown-submenu-parent.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + +.is-dropdown-submenu { + display: none; + position: absolute; + top: 0; + right: 100%; + min-width: 200px; + z-index: 1; + background: #fefefe; + border: 1px solid #cacaca; } + .is-dropdown-submenu .is-dropdown-submenu-parent > a::after { + left: 14px; + margin-top: -3px; } + .is-dropdown-submenu .is-dropdown-submenu-parent.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .is-dropdown-submenu .is-dropdown-submenu-parent.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } + .is-dropdown-submenu .is-dropdown-submenu { + margin-top: -1px; } + .is-dropdown-submenu > li { + width: 100%; } + .is-dropdown-submenu.js-dropdown-active { + display: block; } + +.flex-video { + position: relative; + height: 0; + padding-bottom: 75%; + margin-bottom: 1rem; + overflow: hidden; } + .flex-video iframe, + .flex-video object, + .flex-video embed, + .flex-video video { + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 100%; } + .flex-video.widescreen { + padding-bottom: 56.25%; } + .flex-video.vimeo { + padding-top: 0; } + +.label { + display: inline-block; + padding: 0.33333rem 0.5rem; + font-size: 0.8rem; + line-height: 1; + white-space: nowrap; + cursor: default; + border-radius: 0; + background: #2199e8; + color: #fefefe; } + .label.secondary { + background: #777; + color: #fefefe; } + .label.success { + background: #3adb76; + color: #fefefe; } + .label.warning { + background: #ffae00; + color: #fefefe; } + .label.alert { + background: #ec5840; + color: #fefefe; } + +.media-object { + margin-bottom: 1rem; + display: block; } + .media-object img { + max-width: none; } + @media screen and (max-width: 39.9375em) { + .media-object.stack-for-small .media-object-section { + padding: 0; + padding-bottom: 1rem; + display: block; } + .media-object.stack-for-small .media-object-section img { + width: 100%; } } + +.media-object-section { + display: table-cell; + vertical-align: top; } + .media-object-section:first-child { + padding-left: 1rem; } + .media-object-section:last-child:not(:nth-child(2)) { + padding-right: 1rem; } + .media-object-section > :last-child { + margin-bottom: 0; } + .media-object-section.middle { + vertical-align: middle; } + .media-object-section.bottom { + vertical-align: bottom; } + +html, +body { + height: 100%; } + +.off-canvas-wrapper { + width: 100%; + overflow-x: hidden; + position: relative; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-overflow-scrolling: auto; } + +.off-canvas-wrapper-inner { + position: relative; + width: 100%; + min-height: 100%; + -webkit-transition: -webkit-transform 0.5s ease; + transition: transform 0.5s ease; } + .off-canvas-wrapper-inner::before, .off-canvas-wrapper-inner::after { + content: ' '; + display: table; } + .off-canvas-wrapper-inner::after { + clear: both; } + +.off-canvas-content, +.off-canvas-content { + min-height: 100%; + background: #fefefe; + -webkit-transition: -webkit-transform 0.5s ease; + transition: transform 0.5s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + z-index: 1; + padding-bottom: 0.1px; + -webkit-box-shadow: 0 0 10px rgba(10, 10, 10, 0.5); + box-shadow: 0 0 10px rgba(10, 10, 10, 0.5); } + +.js-off-canvas-exit { + display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(254, 254, 254, 0.25); + cursor: pointer; + -webkit-transition: background 0.5s ease; + transition: background 0.5s ease; } + +.off-canvas { + position: absolute; + background: #e6e6e6; + z-index: -1; + max-height: 100%; + overflow-y: auto; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); } + [data-whatinput='mouse'] .off-canvas { + outline: 0; } + .off-canvas.position-left { + left: -250px; + top: 0; + width: 250px; } + .is-open-left { + -webkit-transform: translateX(250px); + -ms-transform: translateX(250px); + transform: translateX(250px); } + .off-canvas.position-right { + right: -250px; + top: 0; + width: 250px; } + .is-open-right { + -webkit-transform: translateX(-250px); + -ms-transform: translateX(-250px); + transform: translateX(-250px); } + +@media screen and (min-width: 40em) { + .position-left.reveal-for-medium { + left: 0; + z-index: auto; + position: fixed; } + .position-left.reveal-for-medium ~ .off-canvas-content { + margin-left: 250px; } + .position-right.reveal-for-medium { + right: 0; + z-index: auto; + position: fixed; } + .position-right.reveal-for-medium ~ .off-canvas-content { + margin-right: 250px; } } + +@media screen and (min-width: 64em) { + .position-left.reveal-for-large { + left: 0; + z-index: auto; + position: fixed; } + .position-left.reveal-for-large ~ .off-canvas-content { + margin-left: 250px; } + .position-right.reveal-for-large { + right: 0; + z-index: auto; + position: fixed; } + .position-right.reveal-for-large ~ .off-canvas-content { + margin-right: 250px; } } + +.orbit { + position: relative; } + +.orbit-container { + position: relative; + margin: 0; + overflow: hidden; + list-style: none; } + +.orbit-slide { + width: 100%; + max-height: 100%; } + .orbit-slide.no-motionui.is-active { + top: 0; + left: 0; } + +.orbit-figure { + margin: 0; } + +.orbit-image { + margin: 0; + width: 100%; + max-width: 100%; } + +.orbit-caption { + position: absolute; + bottom: 0; + width: 100%; + padding: 1rem; + margin-bottom: 0; + color: #fefefe; + background-color: rgba(10, 10, 10, 0.5); } + +.orbit-previous, .orbit-next { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + z-index: 10; + padding: 1rem; + color: #fefefe; } + [data-whatinput='mouse'] .orbit-previous, [data-whatinput='mouse'] .orbit-next { + outline: 0; } + .orbit-previous:hover, .orbit-next:hover, .orbit-previous:active, .orbit-next:active, .orbit-previous:focus, .orbit-next:focus { + background-color: rgba(10, 10, 10, 0.5); } + +.orbit-previous { + right: 0; } + +.orbit-next { + right: auto; + left: 0; } + +.orbit-bullets { + position: relative; + margin-top: 0.8rem; + margin-bottom: 0.8rem; + text-align: center; } + [data-whatinput='mouse'] .orbit-bullets { + outline: 0; } + .orbit-bullets button { + width: 1.2rem; + height: 1.2rem; + margin: 0.1rem; + background-color: #cacaca; + border-radius: 50%; } + .orbit-bullets button:hover { + background-color: #8a8a8a; } + .orbit-bullets button.is-active { + background-color: #8a8a8a; } + +.pagination { + margin-right: 0; + margin-bottom: 1rem; } + .pagination::before, .pagination::after { + content: ' '; + display: table; } + .pagination::after { + clear: both; } + .pagination li { + font-size: 0.875rem; + margin-left: 0.0625rem; + border-radius: 0; + display: none; } + .pagination li:last-child, .pagination li:first-child { + display: inline-block; } + @media screen and (min-width: 40em) { + .pagination li { + display: inline-block; } } + .pagination a, + .pagination button { + color: #0a0a0a; + display: block; + padding: 0.1875rem 0.625rem; + border-radius: 0; } + .pagination a:hover, + .pagination button:hover { + background: #e6e6e6; } + .pagination .current { + padding: 0.1875rem 0.625rem; + background: #2199e8; + color: #fefefe; + cursor: default; } + .pagination .disabled { + padding: 0.1875rem 0.625rem; + color: #cacaca; + cursor: not-allowed; } + .pagination .disabled:hover { + background: transparent; } + .pagination .ellipsis::after { + content: '\2026'; + padding: 0.1875rem 0.625rem; + color: #0a0a0a; } + +.pagination-previous a::before, +.pagination-previous.disabled::before { + content: '\00ab'; + display: inline-block; + margin-left: 0.5rem; } + +.pagination-next a::after, +.pagination-next.disabled::after { + content: '\00bb'; + display: inline-block; + margin-right: 0.5rem; } + +.progress { + background-color: #cacaca; + height: 1rem; + margin-bottom: 1rem; + border-radius: 0; } + .progress.primary .progress-meter { + background-color: #2199e8; } + .progress.secondary .progress-meter { + background-color: #777; } + .progress.success .progress-meter { + background-color: #3adb76; } + .progress.warning .progress-meter { + background-color: #ffae00; } + .progress.alert .progress-meter { + background-color: #ec5840; } + +.progress-meter { + position: relative; + display: block; + width: 0%; + height: 100%; + background-color: #2199e8; } + +.progress-meter-text { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + position: absolute; + margin: 0; + font-size: 0.75rem; + font-weight: bold; + color: #fefefe; + white-space: nowrap; } + +.slider { + position: relative; + height: 0.5rem; + margin-top: 1.25rem; + margin-bottom: 2.25rem; + background-color: #e6e6e6; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -ms-touch-action: none; + touch-action: none; } + +.slider-fill { + position: absolute; + top: 0; + left: 0; + display: inline-block; + max-width: 100%; + height: 0.5rem; + background-color: #cacaca; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + .slider-fill.is-dragging { + -webkit-transition: all 0s linear; + transition: all 0s linear; } + +.slider-handle { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + position: absolute; + left: 0; + z-index: 1; + display: inline-block; + width: 1.4rem; + height: 1.4rem; + background-color: #2199e8; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -ms-touch-action: manipulation; + touch-action: manipulation; + border-radius: 0; } + [data-whatinput='mouse'] .slider-handle { + outline: 0; } + .slider-handle:hover { + background-color: #1583cc; } + .slider-handle.is-dragging { + -webkit-transition: all 0s linear; + transition: all 0s linear; } + +.slider.disabled, +.slider[disabled] { + opacity: 0.25; + cursor: not-allowed; } + +.slider.vertical { + display: inline-block; + width: 0.5rem; + height: 12.5rem; + margin: 0 1.25rem; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); } + .slider.vertical .slider-fill { + top: 0; + width: 0.5rem; + max-height: 100%; } + .slider.vertical .slider-handle { + position: absolute; + top: 0; + left: 50%; + width: 1.4rem; + height: 1.4rem; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + +.slider:not(.vertical) { + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.sticky-container { + position: relative; } + +.sticky { + position: absolute; + z-index: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.sticky.is-stuck { + position: fixed; + z-index: 5; } + .sticky.is-stuck.is-at-top { + top: 0; } + .sticky.is-stuck.is-at-bottom { + bottom: 0; } + +.sticky.is-anchored { + position: absolute; + left: auto; + right: auto; } + .sticky.is-anchored.is-at-bottom { + bottom: 0; } + +body.is-reveal-open { + overflow: hidden; } + +html.is-reveal-open, +html.is-reveal-open body { + min-height: 100%; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +.reveal-overlay { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1005; + background-color: rgba(10, 10, 10, 0.45); + overflow-y: scroll; } + +.reveal { + display: none; + z-index: 1006; + padding: 1rem; + border: 1px solid #cacaca; + background-color: #fefefe; + border-radius: 0; + position: relative; + top: 100px; + margin-left: auto; + margin-right: auto; + overflow-y: auto; } + [data-whatinput='mouse'] .reveal { + outline: 0; } + @media screen and (min-width: 40em) { + .reveal { + min-height: 0; } } + .reveal .column, .reveal .columns, + .reveal .columns { + min-width: 0; } + .reveal > :last-child { + margin-bottom: 0; } + @media screen and (min-width: 40em) { + .reveal { + width: 600px; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal .reveal { + left: auto; + right: auto; + margin: 0 auto; } } + .reveal.collapse { + padding: 0; } + @media screen and (min-width: 40em) { + .reveal.tiny { + width: 30%; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal.small { + width: 50%; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal.large { + width: 90%; + max-width: 75rem; } } + .reveal.full { + top: 0; + left: 0; + width: 100%; + height: 100%; + height: 100vh; + min-height: 100vh; + max-width: none; + margin-left: 0; + border: 0; + border-radius: 0; } + @media screen and (max-width: 39.9375em) { + .reveal { + top: 0; + left: 0; + width: 100%; + height: 100%; + height: 100vh; + min-height: 100vh; + max-width: none; + margin-left: 0; + border: 0; + border-radius: 0; } } + .reveal.without-overlay { + position: fixed; } + +.switch { + height: 2rem; + margin-bottom: 1rem; + outline: 0; + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + color: #fefefe; + font-weight: bold; + font-size: 0.875rem; } + +.switch-input { + opacity: 0; + position: absolute; + margin-bottom: 0; } + +.switch-paddle { + background: #cacaca; + cursor: pointer; + display: block; + position: relative; + width: 4rem; + height: 2rem; + -webkit-transition: all 0.25s ease-out; + transition: all 0.25s ease-out; + border-radius: 0; + color: inherit; + font-weight: inherit; } + input + .switch-paddle { + margin: 0; } + .switch-paddle::after { + background: #fefefe; + content: ''; + display: block; + position: absolute; + height: 1.5rem; + right: 0.25rem; + top: 0.25rem; + width: 1.5rem; + -webkit-transition: all 0.25s ease-out; + transition: all 0.25s ease-out; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + border-radius: 0; } + input:checked ~ .switch-paddle { + background: #2199e8; } + input:checked ~ .switch-paddle::after { + right: 2.25rem; } + [data-whatinput='mouse'] input:focus ~ .switch-paddle { + outline: 0; } + +.switch-active, .switch-inactive { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.switch-active { + right: 8%; + display: none; } + input:checked + label > .switch-active { + display: block; } + +.switch-inactive { + left: 15%; } + input:checked + label > .switch-inactive { + display: none; } + +.switch.tiny { + height: 1.5rem; } + .switch.tiny .switch-paddle { + width: 3rem; + height: 1.5rem; + font-size: 0.625rem; } + .switch.tiny .switch-paddle::after { + width: 1rem; + height: 1rem; } + .switch.tiny input:checked ~ .switch-paddle::after { + right: 1.75rem; } + +.switch.small { + height: 1.75rem; } + .switch.small .switch-paddle { + width: 3.5rem; + height: 1.75rem; + font-size: 0.75rem; } + .switch.small .switch-paddle::after { + width: 1.25rem; + height: 1.25rem; } + .switch.small input:checked ~ .switch-paddle::after { + right: 2rem; } + +.switch.large { + height: 2.5rem; } + .switch.large .switch-paddle { + width: 5rem; + height: 2.5rem; + font-size: 1rem; } + .switch.large .switch-paddle::after { + width: 2rem; + height: 2rem; } + .switch.large input:checked ~ .switch-paddle::after { + right: 2.75rem; } + +table { + width: 100%; + margin-bottom: 1rem; + border-radius: 0; } + table thead, + table tbody, + table tfoot { + border: 1px solid #f1f1f1; + background-color: #fefefe; } + table caption { + font-weight: bold; + padding: 0.5rem 0.625rem 0.625rem; } + table thead { + background: #f8f8f8; + color: #0a0a0a; } + table tfoot { + background: #f1f1f1; + color: #0a0a0a; } + table thead tr, + table tfoot tr { + background: transparent; } + table thead th, + table thead td, + table tfoot th, + table tfoot td { + padding: 0.5rem 0.625rem 0.625rem; + font-weight: bold; + text-align: right; } + table tbody tr:nth-child(even) { + background-color: #f1f1f1; } + table tbody th, + table tbody td { + padding: 0.5rem 0.625rem 0.625rem; } + +@media screen and (max-width: 63.9375em) { + table.stack thead { + display: none; } + table.stack tfoot { + display: none; } + table.stack tr, + table.stack th, + table.stack td { + display: block; } + table.stack td { + border-top: 0; } } + +table.scroll { + display: block; + width: 100%; + overflow-x: auto; } + +table.hover thead tr:hover { + background-color: #f3f3f3; } + +table.hover tfoot tr:hover { + background-color: #ececec; } + +table.hover tbody tr:hover { + background-color: #f9f9f9; } + +table.hover tbody tr:nth-of-type(even):hover { + background-color: #ececec; } + +.table-scroll { + overflow-x: auto; } + .table-scroll table { + width: auto; } + +.tabs { + margin: 0; + list-style-type: none; + background: #fefefe; + border: 1px solid #e6e6e6; } + .tabs::before, .tabs::after { + content: ' '; + display: table; } + .tabs::after { + clear: both; } + +.tabs.vertical > li { + width: auto; + float: none; + display: block; } + +.tabs.simple > li > a { + padding: 0; } + .tabs.simple > li > a:hover { + background: transparent; } + +.tabs.primary { + background: #2199e8; } + .tabs.primary > li > a { + color: #fefefe; } + .tabs.primary > li > a:hover, .tabs.primary > li > a:focus { + background: #1893e4; } + +.tabs-title { + float: right; } + .tabs-title > a { + display: block; + padding: 1.25rem 1.5rem; + line-height: 1; + font-size: 0.75rem; } + .tabs-title > a:hover { + background: #fefefe; } + .tabs-title > a:focus, .tabs-title > a[aria-selected='true'] { + background: #e6e6e6; } + +.tabs-content { + background: #fefefe; + -webkit-transition: all 0.5s ease; + transition: all 0.5s ease; + border: 1px solid #e6e6e6; + border-top: 0; } + +.tabs-content.vertical { + border: 1px solid #e6e6e6; + border-right: 0; } + +.tabs-panel { + display: none; + padding: 1rem; } + .tabs-panel.is-active { + display: block; } + +.thumbnail { + border: solid 4px #fefefe; + -webkit-box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2); + box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2); + display: inline-block; + line-height: 0; + max-width: 100%; + -webkit-transition: -webkit-box-shadow 200ms ease-out; + transition: box-shadow 200ms ease-out; + border-radius: 0; + margin-bottom: 1rem; } + .thumbnail:hover, .thumbnail:focus { + -webkit-box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); + box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); } + +.title-bar { + background: #0a0a0a; + color: #fefefe; + padding: 0.5rem; } + .title-bar::before, .title-bar::after { + content: ' '; + display: table; } + .title-bar::after { + clear: both; } + .title-bar .menu-icon { + margin-right: 0.25rem; + margin-left: 0.25rem; } + +.title-bar-left { + float: left; } + +.title-bar-right { + float: right; + text-align: right; } + +.title-bar-title { + font-weight: bold; + vertical-align: middle; + display: inline-block; } + +.has-tip { + border-bottom: dotted 1px #8a8a8a; + font-weight: bold; + position: relative; + display: inline-block; + cursor: help; } + +.tooltip { + background-color: #0a0a0a; + color: #fefefe; + font-size: 80%; + padding: 0.75rem; + position: absolute; + z-index: 10; + top: calc(100% + 0.6495rem); + max-width: 10rem !important; + border-radius: 0; } + .tooltip::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent transparent #0a0a0a; + border-bottom-style: solid; + border-top-width: 0; + bottom: 100%; + position: absolute; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + .tooltip.top::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: #0a0a0a transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + top: 100%; + bottom: auto; } + .tooltip.left::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent transparent transparent #0a0a0a; + border-left-style: solid; + border-right-width: 0; + bottom: auto; + left: 100%; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .tooltip.right::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent #0a0a0a transparent transparent; + border-right-style: solid; + border-left-width: 0; + bottom: auto; + left: auto; + right: 100%; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.top-bar { + padding: 0.5rem; } + .top-bar::before, .top-bar::after { + content: ' '; + display: table; } + .top-bar::after { + clear: both; } + .top-bar, + .top-bar ul { + background-color: #e6e6e6; } + .top-bar input { + max-width: 200px; + margin-left: 1rem; } + .top-bar .input-group-field { + width: 100%; + margin-left: 0; } + .top-bar input.button { + width: auto; } + .top-bar .top-bar-left, + .top-bar .top-bar-right { + width: 100%; } + @media screen and (min-width: 40em) { + .top-bar .top-bar-left, + .top-bar .top-bar-right { + width: auto; } } + @media screen and (max-width: 63.9375em) { + .top-bar.stacked-for-medium .top-bar-left, + .top-bar.stacked-for-medium .top-bar-right { + width: 100%; } } + @media screen and (max-width: 74.9375em) { + .top-bar.stacked-for-large .top-bar-left, + .top-bar.stacked-for-large .top-bar-right { + width: 100%; } } + +.top-bar-title { + float: left; + margin-right: 1rem; } + +.top-bar-left { + float: left; } + +.top-bar-right { + float: right; } + +.hide { + display: none !important; } + +.invisible { + visibility: hidden; } + +@media screen and (max-width: 39.9375em) { + .hide-for-small-only { + display: none !important; } } + +@media screen and (max-width: 0em), screen and (min-width: 40em) { + .show-for-small-only { + display: none !important; } } + +@media screen and (min-width: 40em) { + .hide-for-medium { + display: none !important; } } + +@media screen and (max-width: 39.9375em) { + .show-for-medium { + display: none !important; } } + +@media screen and (min-width: 40em) and (max-width: 63.9375em) { + .hide-for-medium-only { + display: none !important; } } + +@media screen and (max-width: 39.9375em), screen and (min-width: 64em) { + .show-for-medium-only { + display: none !important; } } + +@media screen and (min-width: 64em) { + .hide-for-large { + display: none !important; } } + +@media screen and (max-width: 63.9375em) { + .show-for-large { + display: none !important; } } + +@media screen and (min-width: 64em) and (max-width: 74.9375em) { + .hide-for-large-only { + display: none !important; } } + +@media screen and (max-width: 63.9375em), screen and (min-width: 75em) { + .show-for-large-only { + display: none !important; } } + +.show-for-sr, +.show-on-focus { + position: absolute !important; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); } + +.show-on-focus:active, .show-on-focus:focus { + position: static !important; + height: auto; + width: auto; + overflow: visible; + clip: auto; } + +.show-for-landscape, +.hide-for-portrait { + display: block !important; } + @media screen and (orientation: landscape) { + .show-for-landscape, + .hide-for-portrait { + display: block !important; } } + @media screen and (orientation: portrait) { + .show-for-landscape, + .hide-for-portrait { + display: none !important; } } + +.hide-for-landscape, +.show-for-portrait { + display: none !important; } + @media screen and (orientation: landscape) { + .hide-for-landscape, + .show-for-portrait { + display: none !important; } } + @media screen and (orientation: portrait) { + .hide-for-landscape, + .show-for-portrait { + display: block !important; } } + +.float-left { + float: left !important; } + +.float-right { + float: right !important; } + +.float-center { + display: block; + margin-left: auto; + margin-right: auto; } + +.clearfix::before, .clearfix::after { + content: ' '; + display: table; } + +.clearfix::after { + clear: both; } + +/*# sourceMappingURL=foundation-rtl.css.map */ diff --git a/sopds_web_backend/static/css/foundation-rtl.min.css b/sopds_web_backend/static/css/foundation-rtl.min.css new file mode 100644 index 0000000000000000000000000000000000000000..3cff5f4c9772e0dc8da2f94c95390959ffce4201 --- /dev/null +++ b/sopds_web_backend/static/css/foundation-rtl.min.css @@ -0,0 +1,2 @@ +@charset "UTF-8"; +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:not-allowed}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{font-size:100%;box-sizing:border-box}*,:after,:before{box-sizing:inherit}body{padding:0;margin:0;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;color:#0a0a0a;background:#fefefe;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}img{max-width:100%;height:auto;-ms-interpolation-mode:bicubic;display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px;border-radius:0}select{width:100%;border-radius:0}#map_canvas embed,#map_canvas img,#map_canvas object,.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;background:transparent;padding:0;border:0;border-radius:0;line-height:1}[data-whatinput=mouse] button{outline:0}.is-visible{display:block!important}.is-hidden{display:none!important}.row{max-width:75rem;margin-left:auto;margin-right:auto}.row:after,.row:before{content:' ';display:table}.row:after{clear:both}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0}.row .row{margin-left:-.625rem;margin-right:-.625rem}@media screen and (min-width:40em){.row .row{margin-left:-.9375rem;margin-right:-.9375rem}}.row .row.collapse{margin-left:0;margin-right:0}.row.expanded{max-width:none}.row.expanded .row{margin-left:auto;margin-right:auto}.column,.columns{width:100%;float:right;padding-left:.625rem;padding-right:.625rem}@media screen and (min-width:40em){.column,.columns{padding-left:.9375rem;padding-right:.9375rem}}.column:last-child:not(:first-child),.columns:last-child:not(:first-child){float:left}.column.end:last-child:last-child,.end.columns:last-child:last-child{float:right}.column.row.row,.row.row.columns{float:none}.row .column.row.row,.row .row.row.columns{padding-left:0;padding-right:0;margin-left:0;margin-right:0}.small-1{width:8.33333%}.small-push-1{position:relative;right:8.33333%}.small-pull-1{position:relative;right:-8.33333%}.small-offset-0{margin-right:0}.small-2{width:16.66667%}.small-push-2{position:relative;right:16.66667%}.small-pull-2{position:relative;right:-16.66667%}.small-offset-1{margin-right:8.33333%}.small-3{width:25%}.small-push-3{position:relative;right:25%}.small-pull-3{position:relative;right:-25%}.small-offset-2{margin-right:16.66667%}.small-4{width:33.33333%}.small-push-4{position:relative;right:33.33333%}.small-pull-4{position:relative;right:-33.33333%}.small-offset-3{margin-right:25%}.small-5{width:41.66667%}.small-push-5{position:relative;right:41.66667%}.small-pull-5{position:relative;right:-41.66667%}.small-offset-4{margin-right:33.33333%}.small-6{width:50%}.small-push-6{position:relative;right:50%}.small-pull-6{position:relative;right:-50%}.small-offset-5{margin-right:41.66667%}.small-7{width:58.33333%}.small-push-7{position:relative;right:58.33333%}.small-pull-7{position:relative;right:-58.33333%}.small-offset-6{margin-right:50%}.small-8{width:66.66667%}.small-push-8{position:relative;right:66.66667%}.small-pull-8{position:relative;right:-66.66667%}.small-offset-7{margin-right:58.33333%}.small-9{width:75%}.small-push-9{position:relative;right:75%}.small-pull-9{position:relative;right:-75%}.small-offset-8{margin-right:66.66667%}.small-10{width:83.33333%}.small-push-10{position:relative;right:83.33333%}.small-pull-10{position:relative;right:-83.33333%}.small-offset-9{margin-right:75%}.small-11{width:91.66667%}.small-push-11{position:relative;right:91.66667%}.small-pull-11{position:relative;right:-91.66667%}.small-offset-10{margin-right:83.33333%}.small-12{width:100%}.small-offset-11{margin-right:91.66667%}.small-up-1>.column,.small-up-1>.columns{width:100%;float:right}.small-up-1>.column:nth-of-type(1n),.small-up-1>.columns:nth-of-type(1n){clear:none}.small-up-1>.column:nth-of-type(1n+1),.small-up-1>.columns:nth-of-type(1n+1){clear:both}.small-up-1>.column:last-child,.small-up-1>.columns:last-child{float:right}.small-up-2>.column,.small-up-2>.columns{width:50%;float:right}.small-up-2>.column:nth-of-type(1n),.small-up-2>.columns:nth-of-type(1n){clear:none}.small-up-2>.column:nth-of-type(2n+1),.small-up-2>.columns:nth-of-type(2n+1){clear:both}.small-up-2>.column:last-child,.small-up-2>.columns:last-child{float:right}.small-up-3>.column,.small-up-3>.columns{width:33.33333%;float:right}.small-up-3>.column:nth-of-type(1n),.small-up-3>.columns:nth-of-type(1n){clear:none}.small-up-3>.column:nth-of-type(3n+1),.small-up-3>.columns:nth-of-type(3n+1){clear:both}.small-up-3>.column:last-child,.small-up-3>.columns:last-child{float:right}.small-up-4>.column,.small-up-4>.columns{width:25%;float:right}.small-up-4>.column:nth-of-type(1n),.small-up-4>.columns:nth-of-type(1n){clear:none}.small-up-4>.column:nth-of-type(4n+1),.small-up-4>.columns:nth-of-type(4n+1){clear:both}.small-up-4>.column:last-child,.small-up-4>.columns:last-child{float:right}.small-up-5>.column,.small-up-5>.columns{width:20%;float:right}.small-up-5>.column:nth-of-type(1n),.small-up-5>.columns:nth-of-type(1n){clear:none}.small-up-5>.column:nth-of-type(5n+1),.small-up-5>.columns:nth-of-type(5n+1){clear:both}.small-up-5>.column:last-child,.small-up-5>.columns:last-child{float:right}.small-up-6>.column,.small-up-6>.columns{width:16.66667%;float:right}.small-up-6>.column:nth-of-type(1n),.small-up-6>.columns:nth-of-type(1n){clear:none}.small-up-6>.column:nth-of-type(6n+1),.small-up-6>.columns:nth-of-type(6n+1){clear:both}.small-up-6>.column:last-child,.small-up-6>.columns:last-child{float:right}.small-up-7>.column,.small-up-7>.columns{width:14.28571%;float:right}.small-up-7>.column:nth-of-type(1n),.small-up-7>.columns:nth-of-type(1n){clear:none}.small-up-7>.column:nth-of-type(7n+1),.small-up-7>.columns:nth-of-type(7n+1){clear:both}.small-up-7>.column:last-child,.small-up-7>.columns:last-child{float:right}.small-up-8>.column,.small-up-8>.columns{width:12.5%;float:right}.small-up-8>.column:nth-of-type(1n),.small-up-8>.columns:nth-of-type(1n){clear:none}.small-up-8>.column:nth-of-type(8n+1),.small-up-8>.columns:nth-of-type(8n+1){clear:both}.small-up-8>.column:last-child,.small-up-8>.columns:last-child{float:right}.small-collapse>.column,.small-collapse>.columns{padding-left:0;padding-right:0}.expanded.row .small-collapse.row,.small-collapse .row{margin-left:0;margin-right:0}.small-uncollapse>.column,.small-uncollapse>.columns{padding-left:.625rem;padding-right:.625rem}.small-centered{margin-left:auto;margin-right:auto}.small-centered,.small-centered:last-child:not(:first-child){float:none;clear:both}.small-pull-0,.small-push-0,.small-uncentered{position:static;margin-left:0;margin-right:0;float:left}@media screen and (min-width:40em){.medium-1{width:8.33333%}.medium-push-1{position:relative;right:8.33333%}.medium-pull-1{position:relative;right:-8.33333%}.medium-offset-0{margin-right:0}.medium-2{width:16.66667%}.medium-push-2{position:relative;right:16.66667%}.medium-pull-2{position:relative;right:-16.66667%}.medium-offset-1{margin-right:8.33333%}.medium-3{width:25%}.medium-push-3{position:relative;right:25%}.medium-pull-3{position:relative;right:-25%}.medium-offset-2{margin-right:16.66667%}.medium-4{width:33.33333%}.medium-push-4{position:relative;right:33.33333%}.medium-pull-4{position:relative;right:-33.33333%}.medium-offset-3{margin-right:25%}.medium-5{width:41.66667%}.medium-push-5{position:relative;right:41.66667%}.medium-pull-5{position:relative;right:-41.66667%}.medium-offset-4{margin-right:33.33333%}.medium-6{width:50%}.medium-push-6{position:relative;right:50%}.medium-pull-6{position:relative;right:-50%}.medium-offset-5{margin-right:41.66667%}.medium-7{width:58.33333%}.medium-push-7{position:relative;right:58.33333%}.medium-pull-7{position:relative;right:-58.33333%}.medium-offset-6{margin-right:50%}.medium-8{width:66.66667%}.medium-push-8{position:relative;right:66.66667%}.medium-pull-8{position:relative;right:-66.66667%}.medium-offset-7{margin-right:58.33333%}.medium-9{width:75%}.medium-push-9{position:relative;right:75%}.medium-pull-9{position:relative;right:-75%}.medium-offset-8{margin-right:66.66667%}.medium-10{width:83.33333%}.medium-push-10{position:relative;right:83.33333%}.medium-pull-10{position:relative;right:-83.33333%}.medium-offset-9{margin-right:75%}.medium-11{width:91.66667%}.medium-push-11{position:relative;right:91.66667%}.medium-pull-11{position:relative;right:-91.66667%}.medium-offset-10{margin-right:83.33333%}.medium-12{width:100%}.medium-offset-11{margin-right:91.66667%}.medium-up-1>.column,.medium-up-1>.columns{width:100%;float:right}.medium-up-1>.column:nth-of-type(1n),.medium-up-1>.columns:nth-of-type(1n){clear:none}.medium-up-1>.column:nth-of-type(1n+1),.medium-up-1>.columns:nth-of-type(1n+1){clear:both}.medium-up-1>.column:last-child,.medium-up-1>.columns:last-child{float:right}.medium-up-2>.column,.medium-up-2>.columns{width:50%;float:right}.medium-up-2>.column:nth-of-type(1n),.medium-up-2>.columns:nth-of-type(1n){clear:none}.medium-up-2>.column:nth-of-type(2n+1),.medium-up-2>.columns:nth-of-type(2n+1){clear:both}.medium-up-2>.column:last-child,.medium-up-2>.columns:last-child{float:right}.medium-up-3>.column,.medium-up-3>.columns{width:33.33333%;float:right}.medium-up-3>.column:nth-of-type(1n),.medium-up-3>.columns:nth-of-type(1n){clear:none}.medium-up-3>.column:nth-of-type(3n+1),.medium-up-3>.columns:nth-of-type(3n+1){clear:both}.medium-up-3>.column:last-child,.medium-up-3>.columns:last-child{float:right}.medium-up-4>.column,.medium-up-4>.columns{width:25%;float:right}.medium-up-4>.column:nth-of-type(1n),.medium-up-4>.columns:nth-of-type(1n){clear:none}.medium-up-4>.column:nth-of-type(4n+1),.medium-up-4>.columns:nth-of-type(4n+1){clear:both}.medium-up-4>.column:last-child,.medium-up-4>.columns:last-child{float:right}.medium-up-5>.column,.medium-up-5>.columns{width:20%;float:right}.medium-up-5>.column:nth-of-type(1n),.medium-up-5>.columns:nth-of-type(1n){clear:none}.medium-up-5>.column:nth-of-type(5n+1),.medium-up-5>.columns:nth-of-type(5n+1){clear:both}.medium-up-5>.column:last-child,.medium-up-5>.columns:last-child{float:right}.medium-up-6>.column,.medium-up-6>.columns{width:16.66667%;float:right}.medium-up-6>.column:nth-of-type(1n),.medium-up-6>.columns:nth-of-type(1n){clear:none}.medium-up-6>.column:nth-of-type(6n+1),.medium-up-6>.columns:nth-of-type(6n+1){clear:both}.medium-up-6>.column:last-child,.medium-up-6>.columns:last-child{float:right}.medium-up-7>.column,.medium-up-7>.columns{width:14.28571%;float:right}.medium-up-7>.column:nth-of-type(1n),.medium-up-7>.columns:nth-of-type(1n){clear:none}.medium-up-7>.column:nth-of-type(7n+1),.medium-up-7>.columns:nth-of-type(7n+1){clear:both}.medium-up-7>.column:last-child,.medium-up-7>.columns:last-child{float:right}.medium-up-8>.column,.medium-up-8>.columns{width:12.5%;float:right}.medium-up-8>.column:nth-of-type(1n),.medium-up-8>.columns:nth-of-type(1n){clear:none}.medium-up-8>.column:nth-of-type(8n+1),.medium-up-8>.columns:nth-of-type(8n+1){clear:both}.medium-up-8>.column:last-child,.medium-up-8>.columns:last-child{float:right}.medium-collapse>.column,.medium-collapse>.columns{padding-left:0;padding-right:0}.expanded.row .medium-collapse.row,.medium-collapse .row{margin-left:0;margin-right:0}.medium-uncollapse>.column,.medium-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.medium-centered{margin-left:auto;margin-right:auto}.medium-centered,.medium-centered:last-child:not(:first-child){float:none;clear:both}.medium-pull-0,.medium-push-0,.medium-uncentered{position:static;margin-left:0;margin-right:0;float:left}}@media screen and (min-width:64em){.large-1{width:8.33333%}.large-push-1{position:relative;right:8.33333%}.large-pull-1{position:relative;right:-8.33333%}.large-offset-0{margin-right:0}.large-2{width:16.66667%}.large-push-2{position:relative;right:16.66667%}.large-pull-2{position:relative;right:-16.66667%}.large-offset-1{margin-right:8.33333%}.large-3{width:25%}.large-push-3{position:relative;right:25%}.large-pull-3{position:relative;right:-25%}.large-offset-2{margin-right:16.66667%}.large-4{width:33.33333%}.large-push-4{position:relative;right:33.33333%}.large-pull-4{position:relative;right:-33.33333%}.large-offset-3{margin-right:25%}.large-5{width:41.66667%}.large-push-5{position:relative;right:41.66667%}.large-pull-5{position:relative;right:-41.66667%}.large-offset-4{margin-right:33.33333%}.large-6{width:50%}.large-push-6{position:relative;right:50%}.large-pull-6{position:relative;right:-50%}.large-offset-5{margin-right:41.66667%}.large-7{width:58.33333%}.large-push-7{position:relative;right:58.33333%}.large-pull-7{position:relative;right:-58.33333%}.large-offset-6{margin-right:50%}.large-8{width:66.66667%}.large-push-8{position:relative;right:66.66667%}.large-pull-8{position:relative;right:-66.66667%}.large-offset-7{margin-right:58.33333%}.large-9{width:75%}.large-push-9{position:relative;right:75%}.large-pull-9{position:relative;right:-75%}.large-offset-8{margin-right:66.66667%}.large-10{width:83.33333%}.large-push-10{position:relative;right:83.33333%}.large-pull-10{position:relative;right:-83.33333%}.large-offset-9{margin-right:75%}.large-11{width:91.66667%}.large-push-11{position:relative;right:91.66667%}.large-pull-11{position:relative;right:-91.66667%}.large-offset-10{margin-right:83.33333%}.large-12{width:100%}.large-offset-11{margin-right:91.66667%}.large-up-1>.column,.large-up-1>.columns{width:100%;float:right}.large-up-1>.column:nth-of-type(1n),.large-up-1>.columns:nth-of-type(1n){clear:none}.large-up-1>.column:nth-of-type(1n+1),.large-up-1>.columns:nth-of-type(1n+1){clear:both}.large-up-1>.column:last-child,.large-up-1>.columns:last-child{float:right}.large-up-2>.column,.large-up-2>.columns{width:50%;float:right}.large-up-2>.column:nth-of-type(1n),.large-up-2>.columns:nth-of-type(1n){clear:none}.large-up-2>.column:nth-of-type(2n+1),.large-up-2>.columns:nth-of-type(2n+1){clear:both}.large-up-2>.column:last-child,.large-up-2>.columns:last-child{float:right}.large-up-3>.column,.large-up-3>.columns{width:33.33333%;float:right}.large-up-3>.column:nth-of-type(1n),.large-up-3>.columns:nth-of-type(1n){clear:none}.large-up-3>.column:nth-of-type(3n+1),.large-up-3>.columns:nth-of-type(3n+1){clear:both}.large-up-3>.column:last-child,.large-up-3>.columns:last-child{float:right}.large-up-4>.column,.large-up-4>.columns{width:25%;float:right}.large-up-4>.column:nth-of-type(1n),.large-up-4>.columns:nth-of-type(1n){clear:none}.large-up-4>.column:nth-of-type(4n+1),.large-up-4>.columns:nth-of-type(4n+1){clear:both}.large-up-4>.column:last-child,.large-up-4>.columns:last-child{float:right}.large-up-5>.column,.large-up-5>.columns{width:20%;float:right}.large-up-5>.column:nth-of-type(1n),.large-up-5>.columns:nth-of-type(1n){clear:none}.large-up-5>.column:nth-of-type(5n+1),.large-up-5>.columns:nth-of-type(5n+1){clear:both}.large-up-5>.column:last-child,.large-up-5>.columns:last-child{float:right}.large-up-6>.column,.large-up-6>.columns{width:16.66667%;float:right}.large-up-6>.column:nth-of-type(1n),.large-up-6>.columns:nth-of-type(1n){clear:none}.large-up-6>.column:nth-of-type(6n+1),.large-up-6>.columns:nth-of-type(6n+1){clear:both}.large-up-6>.column:last-child,.large-up-6>.columns:last-child{float:right}.large-up-7>.column,.large-up-7>.columns{width:14.28571%;float:right}.large-up-7>.column:nth-of-type(1n),.large-up-7>.columns:nth-of-type(1n){clear:none}.large-up-7>.column:nth-of-type(7n+1),.large-up-7>.columns:nth-of-type(7n+1){clear:both}.large-up-7>.column:last-child,.large-up-7>.columns:last-child{float:right}.large-up-8>.column,.large-up-8>.columns{width:12.5%;float:right}.large-up-8>.column:nth-of-type(1n),.large-up-8>.columns:nth-of-type(1n){clear:none}.large-up-8>.column:nth-of-type(8n+1),.large-up-8>.columns:nth-of-type(8n+1){clear:both}.large-up-8>.column:last-child,.large-up-8>.columns:last-child{float:right}.large-collapse>.column,.large-collapse>.columns{padding-left:0;padding-right:0}.expanded.row .large-collapse.row,.large-collapse .row{margin-left:0;margin-right:0}.large-uncollapse>.column,.large-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.large-centered{margin-left:auto;margin-right:auto}.large-centered,.large-centered:last-child:not(:first-child){float:none;clear:both}.large-pull-0,.large-push-0,.large-uncentered{position:static;margin-left:0;margin-right:0;float:left}}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{font-size:inherit;line-height:1.6;margin-bottom:1rem;text-rendering:optimizeLegibility}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}h1,h2,h3,h4,h5,h6{font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;font-style:normal;color:inherit;text-rendering:optimizeLegibility;margin-top:0;margin-bottom:.5rem;line-height:1.4}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.1875rem}h4{font-size:1.125rem}h5{font-size:1.0625rem}h6{font-size:1rem}@media screen and (min-width:40em){h1{font-size:3rem}h2{font-size:2.5rem}h3{font-size:1.9375rem}h4{font-size:1.5625rem}h5{font-size:1.25rem}h6{font-size:1rem}}a{color:#2199e8;text-decoration:none;line-height:inherit;cursor:pointer}a:focus,a:hover{color:#1585cf}a img{border:0}hr{max-width:75rem;height:0;border-right:0;border-top:0;border-bottom:1px solid #cacaca;border-left:0;margin:1.25rem auto;clear:both}dl,ol,ul{line-height:1.6;margin-bottom:1rem;list-style-position:outside}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-right:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-right:1.25rem;margin-bottom:0}dl{margin-bottom:1rem}dl dt{margin-bottom:.3rem;font-weight:700}blockquote{margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem;border-right:1px solid #cacaca}blockquote,blockquote p{line-height:1.6;color:#8a8a8a}cite{display:block;font-size:.8125rem;color:#8a8a8a}cite:before{content:'\2014 \0020'}abbr{color:#0a0a0a;cursor:help;border-bottom:1px dotted #0a0a0a}code{font-weight:400;border:1px solid #cacaca;padding:.125rem .3125rem .0625rem}code,kbd{font-family:Consolas,Liberation Mono,Courier,monospace;color:#0a0a0a;background-color:#e6e6e6}kbd{padding:.125rem .25rem 0;margin:0}.subheader{margin-top:.2rem;margin-bottom:.5rem;font-weight:400;line-height:1.4;color:#8a8a8a}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}.no-bullet{margin-right:0;list-style:none}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^='#']:after,a[href^='javascript:']:after{content:''}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{display:block;box-sizing:border-box;width:100%;height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-family:inherit;font-size:1rem;color:#0a0a0a;background-color:#fefefe;box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);border-radius:0;-webkit-transition:-webkit-box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out;-webkit-appearance:none;-moz-appearance:none}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{border:1px solid #8a8a8a;background-color:#fefefe;outline:none;box-shadow:0 0 5px #cacaca;-webkit-transition:-webkit-box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out}textarea{max-width:100%}textarea[rows]{height:auto}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#cacaca}input::-moz-placeholder,textarea::-moz-placeholder{color:#cacaca}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#cacaca}input::placeholder,textarea::placeholder{color:#cacaca}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{border-radius:0;-webkit-appearance:none;-moz-appearance:none}input[type=search]{box-sizing:border-box}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-right:.5rem;margin-left:1rem;margin-bottom:0;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-left:.5rem}[type=file]{width:100%}label{display:block;margin:0;font-size:.875rem;font-weight:400;line-height:1.8;color:#0a0a0a}label.middle{margin:0 0 1rem;padding:.5625rem 0}.help-text{margin-top:-.5rem;font-size:.8125rem;font-style:italic;color:#0a0a0a}.input-group{display:table;width:100%;margin-bottom:1rem}.input-group>:first-child,.input-group>:last-child>*{border-radius:0 0 0 0}.input-group-button,.input-group-field,.input-group-label{margin:0;white-space:nowrap;display:table-cell;vertical-align:middle}.input-group-label{text-align:center;padding:0 1rem;background:#e6e6e6;color:#0a0a0a;border:1px solid #cacaca;white-space:nowrap;width:1%;height:100%}.input-group-label:first-child{border-left:0}.input-group-label:last-child{border-right:0}.input-group-field{border-radius:0;height:2.5rem}.input-group-button{padding-top:0;padding-bottom:0;text-align:center;height:100%;width:1%}.input-group-button a,.input-group-button button,.input-group-button input{margin:0}.input-group .input-group-button{display:table-cell}fieldset{border:0;padding:0;margin:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;padding:1.25rem;margin:1.125rem 0}.fieldset legend{background:#fefefe;padding:0 .1875rem;margin:0;margin-right:-.1875rem}select{height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-size:1rem;font-family:inherit;line-height:normal;color:#0a0a0a;background-color:#fefefe;border-radius:0;-webkit-appearance:none;-moz-appearance:none;background-image:url("data:image/svg+xml;utf8,");background-size:9px 6px;background-position:left -1rem center;background-origin:content-box;background-repeat:no-repeat;padding-left:1.5rem}@media screen and (min-width:0\0){select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==")}}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{height:auto;background-image:none}.is-invalid-input:not(:focus){background-color:rgba(236,88,64,.1);border-color:#ec5840}.form-error,.is-invalid-label{color:#ec5840}.form-error{display:none;margin-top:-.5rem;margin-bottom:1rem;font-size:.75rem;font-weight:700}.form-error.is-visible{display:block}.button{display:inline-block;text-align:center;line-height:1;cursor:pointer;-webkit-appearance:none;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle;border:1px solid transparent;border-radius:0;padding:.85em 1em;margin:0 0 1rem;font-size:.9rem;background-color:#2199e8;color:#fefefe}[data-whatinput=mouse] .button{outline:0}.button:focus,.button:hover{background-color:#1583cc;color:#fefefe}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;width:100%;margin-left:0;margin-right:0}.button.primary{background-color:#2199e8;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#147cc0;color:#fefefe}.button.secondary{background-color:#777;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5f5f5f;color:#fefefe}.button.success{background-color:#3adb76;color:#fefefe}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#fefefe}.button.warning{background-color:#ffae00;color:#fefefe}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#fefefe}.button.alert{background-color:#ec5840;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#da3116;color:#fefefe}.button.hollow{border:1px solid #2199e8;color:#2199e8}.button.hollow,.button.hollow:focus,.button.hollow:hover{background-color:transparent}.button.hollow:focus,.button.hollow:hover{border-color:#0c4d78;color:#0c4d78}.button.hollow.primary{border:1px solid #2199e8;color:#2199e8}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c4d78;color:#0c4d78}.button.hollow.secondary{border:1px solid #777;color:#777}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3c3c3c;color:#3c3c3c}.button.hollow.success{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert{border:1px solid #ec5840;color:#ec5840}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#881f0e;color:#881f0e}.button.disabled,.button[disabled]{opacity:.25;cursor:not-allowed}.button.disabled:focus,.button.disabled:hover,.button[disabled]:focus,.button[disabled]:hover{background-color:#2199e8;color:#fefefe}.button.disabled.primary,.button[disabled].primary{opacity:.25;cursor:not-allowed}.button.disabled.primary:focus,.button.disabled.primary:hover,.button[disabled].primary:focus,.button[disabled].primary:hover{background-color:#2199e8;color:#fefefe}.button.disabled.secondary,.button[disabled].secondary{opacity:.25;cursor:not-allowed}.button.disabled.secondary:focus,.button.disabled.secondary:hover,.button[disabled].secondary:focus,.button[disabled].secondary:hover{background-color:#777;color:#fefefe}.button.disabled.success,.button[disabled].success{opacity:.25;cursor:not-allowed}.button.disabled.success:focus,.button.disabled.success:hover,.button[disabled].success:focus,.button[disabled].success:hover{background-color:#3adb76;color:#fefefe}.button.disabled.warning,.button[disabled].warning{opacity:.25;cursor:not-allowed}.button.disabled.warning:focus,.button.disabled.warning:hover,.button[disabled].warning:focus,.button[disabled].warning:hover{background-color:#ffae00;color:#fefefe}.button.disabled.alert,.button[disabled].alert{opacity:.25;cursor:not-allowed}.button.disabled.alert:focus,.button.disabled.alert:hover,.button[disabled].alert:focus,.button[disabled].alert:hover{background-color:#ec5840;color:#fefefe}.button.dropdown:after{content:'';display:block;width:0;height:0;border:.4em inset;border-color:#fefefe transparent transparent;border-top-style:solid;border-bottom-width:0;position:relative;top:.4em;float:left;margin-right:1em;display:inline-block}.button.arrow-only:after{margin-right:0;float:none;top:-.1em}.accordion{list-style-type:none;background:#fefefe;margin-right:0}.accordion-item:first-child>:first-child,.accordion-item:last-child>:last-child{border-radius:0 0 0 0}.accordion-title{display:block;padding:1.25rem 1rem;line-height:1;font-size:.75rem;color:#2199e8;position:relative;border:1px solid #e6e6e6;border-bottom:0}:last-child:not(.is-active)>.accordion-title{border-radius:0 0 0 0;border-bottom:1px solid #e6e6e6}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:'+';position:absolute;left:1rem;top:50%;margin-top:-.5rem}.is-active>.accordion-title:before{content:'–'}.accordion-content{padding:1rem;display:none;border:1px solid #e6e6e6;border-bottom:0;background-color:#fefefe;color:#0a0a0a}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.is-accordion-submenu-parent>a{position:relative}.is-accordion-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:6px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;position:absolute;top:50%;margin-top:-4px;right:1rem}.is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform-origin:50% 50%;transform-origin:50% 50%;-webkit-transform:scaleY(-1);transform:scaleY(-1)}.badge{display:inline-block;padding:.3em;min-width:2.1em;font-size:.6rem;text-align:center;border-radius:50%;background:#2199e8;color:#fefefe}.badge.secondary{background:#777;color:#fefefe}.badge.success{background:#3adb76;color:#fefefe}.badge.warning{background:#ffae00;color:#fefefe}.badge.alert{background:#ec5840;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{content:' ';display:table}.breadcrumbs:after{clear:both}.breadcrumbs li{float:right;color:#0a0a0a;font-size:.6875rem;cursor:default;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"\\";margin:0 .75rem;position:relative;top:1px;opacity:1}.breadcrumbs a{color:#2199e8}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.button-group{margin-bottom:1rem;font-size:0}.button-group:after,.button-group:before{content:' ';display:table}.button-group:after{clear:both}.button-group .button{margin:0;margin-left:1px;margin-bottom:1px;font-size:.9rem}.button-group .button:last-child{margin-left:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded{margin-left:-1px}.button-group.expanded:after,.button-group.expanded:before{display:none}.button-group.expanded .button:first-child:nth-last-child(2),.button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2)~.button{display:inline-block;width:calc(50% - 1px);margin-left:1px}.button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(2):last-child{margin-left:-6px}.button-group.expanded .button:first-child:nth-last-child(3),.button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3)~.button{display:inline-block;width:calc(33.33333% - 1px);margin-left:1px}.button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(3):last-child{margin-left:-6px}.button-group.expanded .button:first-child:nth-last-child(4),.button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4)~.button{display:inline-block;width:calc(25% - 1px);margin-left:1px}.button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(4):last-child{margin-left:-6px}.button-group.expanded .button:first-child:nth-last-child(5),.button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5)~.button{display:inline-block;width:calc(20% - 1px);margin-left:1px}.button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(5):last-child{margin-left:-6px}.button-group.expanded .button:first-child:nth-last-child(6),.button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6)~.button{display:inline-block;width:calc(16.66667% - 1px);margin-left:1px}.button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(6):last-child{margin-left:-6px}.button-group.primary .button{background-color:#2199e8;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#147cc0;color:#fefefe}.button-group.secondary .button{background-color:#777;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5f5f5f;color:#fefefe}.button-group.success .button{background-color:#3adb76;color:#fefefe}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#fefefe}.button-group.warning .button{background-color:#ffae00;color:#fefefe}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#fefefe}.button-group.alert .button{background-color:#ec5840;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#da3116;color:#fefefe}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{width:100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}@media screen and (min-width:40em){.button-group.stacked-for-small .button{width:auto;margin-bottom:0}}@media screen and (min-width:64em){.button-group.stacked-for-medium .button{width:auto;margin-bottom:0}}@media screen and (max-width:39.9375em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-left:0}}.callout{margin:0 0 1rem;padding:1rem;border:1px solid hsla(0,0%,4%,.25);border-radius:0;position:relative;color:#0a0a0a;background-color:#fff}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#def0fc}.callout.secondary{background-color:#ebebeb}.callout.success{background-color:#e1faea}.callout.warning{background-color:#fff3d9}.callout.alert{background-color:#fce6e2}.callout.small{padding:.5rem}.callout.large{padding:3rem}.close-button{position:absolute;color:#8a8a8a;right:1rem;top:.5rem;font-size:2em;line-height:1;cursor:pointer}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.menu{margin:0;list-style-type:none}.menu>li{display:table-cell;vertical-align:middle}[data-whatinput=mouse] .menu>li{outline:0}.menu>li>a{display:block;padding:.7rem 1rem;line-height:1}.menu a,.menu button,.menu input{margin-bottom:0}.menu>li>a i,.menu>li>a i+span,.menu>li>a img,.menu>li>a img+span,.menu>li>a svg,.menu>li>a svg+span{vertical-align:middle}.menu>li>a i,.menu>li>a img,.menu>li>a svg{margin-left:.25rem;display:inline-block}.menu>li{display:table-cell}.menu.vertical>li{display:block}@media screen and (min-width:40em){.menu.medium-horizontal>li{display:table-cell}.menu.medium-vertical>li{display:block}}@media screen and (min-width:64em){.menu.large-horizontal>li{display:table-cell}.menu.large-vertical>li{display:block}}.menu.simple li{line-height:1;display:inline-block;margin-left:1rem}.menu.simple a{padding:0}.menu.align-left:after,.menu.align-left:before{content:' ';display:table}.menu.align-left:after{clear:both}.menu.align-left>li{float:left}.menu.expanded{width:100%;display:table;table-layout:fixed}.menu.expanded>li:first-child:last-child{width:100%}.menu.icon-top>li>a{text-align:center}.menu.icon-top>li>a i,.menu.icon-top>li>a img,.menu.icon-top>li>a svg{display:block;margin:0 auto .25rem}.menu.nested{margin-right:1rem}.menu .active>a{color:#fefefe;background:#2199e8}.menu-text{font-weight:700;color:inherit;line-height:1;padding-top:0;padding-bottom:0;padding:.7rem 1rem}.menu-centered{text-align:center}.menu-centered>.menu{display:inline-block}.no-js [data-responsive-menu] ul{display:none}.menu-icon{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon:after{content:'';position:absolute;display:block;width:100%;height:2px;background:#fefefe;top:0;left:0;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe}.menu-icon:hover:after{background:#cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon.dark:after{content:'';position:absolute;display:block;width:100%;height:2px;background:#0a0a0a;top:0;left:0;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a}.menu-icon.dark:hover:after{background:#8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.is-drilldown{position:relative;overflow:hidden}.is-drilldown li{display:block!important}.is-drilldown-submenu{position:absolute;top:0;right:100%;z-index:-1;width:100%;background:#fefefe;-webkit-transition:-webkit-transform .15s linear;transition:transform .15s linear}.is-drilldown-submenu.is-active{z-index:1;display:block;-webkit-transform:translateX(100%);transform:translateX(100%)}.is-drilldown-submenu.is-closing{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.is-drilldown-submenu-parent>a{position:relative}.is-drilldown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:6px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0;position:absolute;top:50%;margin-top:-6px;left:1rem}.js-drilldown-back>a:before{content:'';display:block;width:0;height:0;border:6px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0;display:inline-block;vertical-align:middle;margin-left:.75rem}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:block;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-open{visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-left:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;left:5px;margin-top:-2px}[data-whatinput=mouse] .dropdown.menu a{outline:0}.no-js .dropdown.menu ul{display:none}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.vertical>li>a:after{left:14px;margin-top:-3px}.dropdown.menu.vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}@media screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-left:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;left:5px;margin-top:-2px}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.medium-vertical>li>a:after{left:14px;margin-top:-3px}.dropdown.menu.medium-vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}}@media screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-left:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;left:5px;margin-top:-2px}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.large-vertical>li>a:after{left:14px;margin-top:-3px}.dropdown.menu.large-vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{top:100%;left:auto;right:0}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{position:absolute;top:50%;left:5px;margin-top:-2px}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{top:100%;right:auto}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{right:auto;left:100%}.is-dropdown-submenu{display:none;position:absolute;top:0;right:100%;min-width:200px;z-index:1;background:#fefefe;border:1px solid #cacaca}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{left:14px;margin-top:-3px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.flex-video{position:relative;height:0;padding-bottom:75%;margin-bottom:1rem;overflow:hidden}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video{position:absolute;top:0;right:0;width:100%;height:100%}.flex-video.widescreen{padding-bottom:56.25%}.flex-video.vimeo{padding-top:0}.label{display:inline-block;padding:.33333rem .5rem;font-size:.8rem;line-height:1;white-space:nowrap;cursor:default;border-radius:0;background:#2199e8;color:#fefefe}.label.secondary{background:#777;color:#fefefe}.label.success{background:#3adb76;color:#fefefe}.label.warning{background:#ffae00;color:#fefefe}.label.alert{background:#ec5840;color:#fefefe}.media-object{margin-bottom:1rem;display:block}.media-object img{max-width:none}@media screen and (max-width:39.9375em){.media-object.stack-for-small .media-object-section{padding:0;padding-bottom:1rem;display:block}.media-object.stack-for-small .media-object-section img{width:100%}}.media-object-section{display:table-cell;vertical-align:top}.media-object-section:first-child{padding-left:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-right:1rem}.media-object-section>:last-child{margin-bottom:0}.media-object-section.middle{vertical-align:middle}.media-object-section.bottom{vertical-align:bottom}body,html{height:100%}.off-canvas-wrapper{width:100%;overflow-x:hidden;position:relative;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-overflow-scrolling:auto}.off-canvas-wrapper-inner{position:relative;width:100%;min-height:100%;-webkit-transition:-webkit-transform .5s ease;transition:transform .5s ease}.off-canvas-wrapper-inner:after,.off-canvas-wrapper-inner:before{content:' ';display:table}.off-canvas-wrapper-inner:after{clear:both}.off-canvas-content{min-height:100%;background:#fefefe;-webkit-transition:-webkit-transform .5s ease;transition:transform .5s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1;padding-bottom:.1px;box-shadow:0 0 10px hsla(0,0%,4%,.5)}.js-off-canvas-exit{display:none;position:absolute;top:0;left:0;width:100%;height:100%;background:hsla(0,0%,100%,.25);cursor:pointer;-webkit-transition:background .5s ease;transition:background .5s ease}.off-canvas{position:absolute;background:#e6e6e6;z-index:-1;max-height:100%;overflow-y:auto;-webkit-transform:translateX(0);transform:translateX(0)}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.position-left{left:-250px;top:0;width:250px}.is-open-left{-webkit-transform:translateX(250px);transform:translateX(250px)}.off-canvas.position-right{right:-250px;top:0;width:250px}.is-open-right{-webkit-transform:translateX(-250px);transform:translateX(-250px)}@media screen and (min-width:40em){.position-left.reveal-for-medium{left:0;z-index:auto;position:fixed}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{right:0;z-index:auto;position:fixed}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}}@media screen and (min-width:64em){.position-left.reveal-for-large{left:0;z-index:auto;position:fixed}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{right:0;z-index:auto;position:fixed}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}}.orbit,.orbit-container{position:relative}.orbit-container{margin:0;overflow:hidden;list-style:none}.orbit-slide{width:100%;max-height:100%}.orbit-slide.no-motionui.is-active{top:0;left:0}.orbit-figure{margin:0}.orbit-image{margin:0;width:100%;max-width:100%}.orbit-caption{bottom:0;width:100%;margin-bottom:0;background-color:hsla(0,0%,4%,.5)}.orbit-caption,.orbit-next,.orbit-previous{position:absolute;padding:1rem;color:#fefefe}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{right:0}.orbit-next{right:auto;left:0}.orbit-bullets{position:relative;margin-top:.8rem;margin-bottom:.8rem;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{width:1.2rem;height:1.2rem;margin:.1rem;background-color:#cacaca;border-radius:50%}.orbit-bullets button.is-active,.orbit-bullets button:hover{background-color:#8a8a8a}.pagination{margin-right:0;margin-bottom:1rem}.pagination:after,.pagination:before{content:' ';display:table}.pagination:after{clear:both}.pagination li{font-size:.875rem;margin-left:.0625rem;border-radius:0;display:none}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{color:#0a0a0a;display:block;padding:.1875rem .625rem;border-radius:0}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{padding:.1875rem .625rem;background:#2199e8;color:#fefefe;cursor:default}.pagination .disabled{padding:.1875rem .625rem;color:#cacaca;cursor:not-allowed}.pagination .disabled:hover{background:transparent}.pagination .ellipsis:after{content:'\2026';padding:.1875rem .625rem;color:#0a0a0a}.pagination-previous.disabled:before,.pagination-previous a:before{content:'\00ab';display:inline-block;margin-left:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:'\00bb';display:inline-block;margin-right:.5rem}.progress{background-color:#cacaca;height:1rem;margin-bottom:1rem;border-radius:0}.progress.primary .progress-meter{background-color:#2199e8}.progress.secondary .progress-meter{background-color:#777}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#ec5840}.progress-meter{position:relative;display:block;width:0;height:100%;background-color:#2199e8}.progress-meter-text{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;margin:0;font-size:.75rem;font-weight:700;color:#fefefe;white-space:nowrap}.slider{position:relative;height:.5rem;margin-top:1.25rem;margin-bottom:2.25rem;background-color:#e6e6e6;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-touch-action:none;touch-action:none}.slider-fill{position:absolute;top:0;left:0;display:inline-block;max-width:100%;height:.5rem;background-color:#cacaca;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;left:0;z-index:1;display:inline-block;width:1.4rem;height:1.4rem;background-color:#2199e8;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-ms-touch-action:manipulation;touch-action:manipulation;border-radius:0}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#1583cc}.slider-handle.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{opacity:.25;cursor:not-allowed}.slider.vertical{display:inline-block;width:.5rem;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);transform:scaleY(-1)}.slider.vertical .slider-fill{top:0;width:.5rem;max-height:100%}.slider.vertical .slider-handle{position:absolute;top:0;left:50%;width:1.4rem;height:1.4rem;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.slider:not(.vertical){-webkit-transform:scaleX(-1);transform:scaleX(-1)}.sticky-container{position:relative}.sticky{position:absolute;z-index:0;-webkit-transform:translateZ(0);transform:translateZ(0)}.sticky.is-stuck{position:fixed;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{position:absolute;left:auto;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}body.is-reveal-open{overflow:hidden}html.is-reveal-open,html.is-reveal-open body{min-height:100%;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.reveal-overlay{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:1005;background-color:hsla(0,0%,4%,.45);overflow-y:scroll}.reveal{display:none;z-index:1006;padding:1rem;border:1px solid #cacaca;background-color:#fefefe;border-radius:0;position:relative;top:100px;margin-left:auto;margin-right:auto;overflow-y:auto}[data-whatinput=mouse] .reveal{outline:0}@media screen and (min-width:40em){.reveal{min-height:0}}.reveal .column,.reveal .columns{min-width:0}.reveal>:last-child{margin-bottom:0}@media screen and (min-width:40em){.reveal{width:600px;max-width:75rem}}@media screen and (min-width:40em){.reveal .reveal{left:auto;right:auto;margin:0 auto}}.reveal.collapse{padding:0}@media screen and (min-width:40em){.reveal.tiny{width:30%;max-width:75rem}}@media screen and (min-width:40em){.reveal.small{width:50%;max-width:75rem}}@media screen and (min-width:40em){.reveal.large{width:90%;max-width:75rem}}.reveal.full{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}@media screen and (max-width:39.9375em){.reveal{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}}.reveal.without-overlay{position:fixed}.switch{height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fefefe;font-weight:700;font-size:.875rem}.switch-input{opacity:0;position:absolute;margin-bottom:0}.switch-paddle{background:#cacaca;cursor:pointer;display:block;position:relative;width:4rem;height:2rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;border-radius:0;color:inherit;font-weight:inherit}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;content:'';display:block;position:absolute;height:1.5rem;right:.25rem;top:.25rem;width:1.5rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;-webkit-transform:translateZ(0);transform:translateZ(0);border-radius:0}input:checked~.switch-paddle{background:#2199e8}input:checked~.switch-paddle:after{right:2.25rem}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{right:8%;display:none}input:checked+label>.switch-active{display:block}.switch-inactive{left:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{width:3rem;height:1.5rem;font-size:.625rem}.switch.tiny .switch-paddle:after{width:1rem;height:1rem}.switch.tiny input:checked~.switch-paddle:after{right:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{width:3.5rem;height:1.75rem;font-size:.75rem}.switch.small .switch-paddle:after{width:1.25rem;height:1.25rem}.switch.small input:checked~.switch-paddle:after{right:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{width:5rem;height:2.5rem;font-size:1rem}.switch.large .switch-paddle:after{width:2rem;height:2rem}.switch.large input:checked~.switch-paddle:after{right:2.75rem}table{width:100%;margin-bottom:1rem;border-radius:0}table tbody,table tfoot,table thead{border:1px solid #f1f1f1;background-color:#fefefe}table caption{font-weight:700;padding:.5rem .625rem .625rem}table thead{background:#f8f8f8;color:#0a0a0a}table tfoot{background:#f1f1f1;color:#0a0a0a}table tfoot tr,table thead tr{background:transparent}table tfoot td,table tfoot th,table thead td,table thead th{padding:.5rem .625rem .625rem;font-weight:700;text-align:right}table tbody tr:nth-child(even){background-color:#f1f1f1}table tbody td,table tbody th{padding:.5rem .625rem .625rem}@media screen and (max-width:63.9375em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;width:100%;overflow-x:auto}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover tbody tr:nth-of-type(even):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.table-scroll table{width:auto}.tabs{margin:0;list-style-type:none;background:#fefefe;border:1px solid #e6e6e6}.tabs:after,.tabs:before{content:' ';display:table}.tabs:after{clear:both}.tabs.vertical>li{width:auto;float:none;display:block}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:transparent}.tabs.primary{background:#2199e8}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1893e4}.tabs-title{float:right}.tabs-title>a{display:block;padding:1.25rem 1.5rem;line-height:1;font-size:.75rem}.tabs-title>a:hover{background:#fefefe}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6}.tabs-content{background:#fefefe;-webkit-transition:all .5s ease;transition:all .5s ease;border:1px solid #e6e6e6;border-top:0}.tabs-content.vertical{border:1px solid #e6e6e6;border-right:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;max-width:100%;-webkit-transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;border-radius:0;margin-bottom:1rem}.thumbnail:focus,.thumbnail:hover{box-shadow:0 0 6px 1px rgba(33,153,232,.5)}.title-bar{background:#0a0a0a;color:#fefefe;padding:.5rem}.title-bar:after,.title-bar:before{content:' ';display:table}.title-bar:after{clear:both}.title-bar .menu-icon{margin-right:.25rem;margin-left:.25rem}.title-bar-left{float:left}.title-bar-right{float:right;text-align:right}.title-bar-title{vertical-align:middle}.has-tip,.title-bar-title{font-weight:700;display:inline-block}.has-tip{border-bottom:1px dotted #8a8a8a;position:relative;cursor:help}.tooltip{background-color:#0a0a0a;color:#fefefe;font-size:80%;padding:.75rem;position:absolute;z-index:10;top:calc(100% + .6495rem);max-width:10rem!important;border-radius:0}.tooltip:before{border:.75rem inset;border-color:transparent transparent #0a0a0a;border-bottom-style:solid;border-top-width:0;bottom:100%;position:absolute;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before,.tooltip:before{content:'';display:block;width:0;height:0}.tooltip.top:before{border:.75rem inset;border-color:#0a0a0a transparent transparent;border-top-style:solid;border-bottom-width:0;top:100%;bottom:auto}.tooltip.left:before{border:.75rem inset;border-color:transparent transparent transparent #0a0a0a;border-left-style:solid;border-right-width:0;left:100%}.tooltip.left:before,.tooltip.right:before{content:'';display:block;width:0;height:0;bottom:auto;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border:.75rem inset;border-color:transparent #0a0a0a transparent transparent;border-right-style:solid;border-left-width:0;left:auto;right:100%}.top-bar{padding:.5rem}.top-bar:after,.top-bar:before{content:' ';display:table}.top-bar:after{clear:both}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{max-width:200px;margin-left:1rem}.top-bar .input-group-field{width:100%;margin-left:0}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{width:100%}@media screen and (min-width:40em){.top-bar .top-bar-left,.top-bar .top-bar-right{width:auto}}@media screen and (max-width:63.9375em){.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{width:100%}}@media screen and (max-width:74.9375em){.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{width:100%}}.top-bar-title{float:left;margin-right:1rem}.top-bar-left{float:left}.top-bar-right{float:right}.hide{display:none!important}.invisible{visibility:hidden}@media screen and (max-width:39.9375em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.9375em){.show-for-medium{display:none!important}}@media screen and (min-width:40em) and (max-width:63.9375em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.9375em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.9375em){.show-for-large{display:none!important}}@media screen and (min-width:64em) and (max-width:74.9375em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.9375em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}.show-on-focus:active,.show-on-focus:focus{position:static!important;height:auto;width:auto;overflow:visible;clip:auto}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{content:' ';display:table}.clearfix:after{clear:both} \ No newline at end of file diff --git a/sopds_web_backend/static/css/foundation.css b/sopds_web_backend/static/css/foundation.css new file mode 100644 index 0000000000000000000000000000000000000000..b715f4b8b6c698955e43ebb6f5e8ca5cca9af6ac --- /dev/null +++ b/sopds_web_backend/static/css/foundation.css @@ -0,0 +1,3608 @@ +@charset "UTF-8"; +/** + * Foundation for Sites by ZURB + * Version 6.2.4 + * foundation.zurb.com + * Licensed under MIT Open Source + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS and IE text size adjust after device orientation change, + * without disabling user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability of focused elements when they are also in an + * active/hover state. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: not-allowed; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome. + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -webkit-box-sizing: content-box; + box-sizing: content-box; + /* 2 */ } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + * [NOTE] We don't enable this ruleset in Foundation, because we want the
element to have plain styling. + */ +/* fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; + } */ +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +.foundation-mq { + font-family: "small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"; } + +html { + font-size: 100%; + -webkit-box-sizing: border-box; + box-sizing: border-box; } + +*, +*::before, +*::after { + -webkit-box-sizing: inherit; + box-sizing: inherit; } + +body { + padding: 0; + margin: 0; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + line-height: 1.5; + color: #0a0a0a; + background: #fefefe; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + +img { + max-width: 100%; + height: auto; + -ms-interpolation-mode: bicubic; + display: inline-block; + vertical-align: middle; } + +textarea { + height: auto; + min-height: 50px; + border-radius: 0; } + +select { + width: 100%; + border-radius: 0; } + +#map_canvas img, +#map_canvas embed, +#map_canvas object, +.map_canvas img, +.map_canvas embed, +.map_canvas object, +.mqa-display img, +.mqa-display embed, +.mqa-display object { + max-width: none !important; } + +button { + -webkit-appearance: none; + -moz-appearance: none; + background: transparent; + padding: 0; + border: 0; + border-radius: 0; + line-height: 1; } + [data-whatinput='mouse'] button { + outline: 0; } + +.is-visible { + display: block !important; } + +.is-hidden { + display: none !important; } + +.row { + max-width: 75rem; + margin-left: auto; + margin-right: auto; } + .row::before, .row::after { + content: ' '; + display: table; } + .row::after { + clear: both; } + .row.collapse > .column, .row.collapse > .columns { + padding-left: 0; + padding-right: 0; } + .row .row { + margin-left: -0.625rem; + margin-right: -0.625rem; } + @media screen and (min-width: 40em) { + .row .row { + margin-left: -0.9375rem; + margin-right: -0.9375rem; } } + .row .row.collapse { + margin-left: 0; + margin-right: 0; } + .row.expanded { + max-width: none; } + .row.expanded .row { + margin-left: auto; + margin-right: auto; } + +.column, .columns { + width: 100%; + float: left; + padding-left: 0.625rem; + padding-right: 0.625rem; } + @media screen and (min-width: 40em) { + .column, .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } } + .column:last-child:not(:first-child), .columns:last-child:not(:first-child) { + float: right; } + .column.end:last-child:last-child, .end.columns:last-child:last-child { + float: left; } + +.column.row.row, .row.row.columns { + float: none; } + +.row .column.row.row, .row .row.row.columns { + padding-left: 0; + padding-right: 0; + margin-left: 0; + margin-right: 0; } + +.small-1 { + width: 8.33333%; } + +.small-push-1 { + position: relative; + left: 8.33333%; } + +.small-pull-1 { + position: relative; + left: -8.33333%; } + +.small-offset-0 { + margin-left: 0%; } + +.small-2 { + width: 16.66667%; } + +.small-push-2 { + position: relative; + left: 16.66667%; } + +.small-pull-2 { + position: relative; + left: -16.66667%; } + +.small-offset-1 { + margin-left: 8.33333%; } + +.small-3 { + width: 25%; } + +.small-push-3 { + position: relative; + left: 25%; } + +.small-pull-3 { + position: relative; + left: -25%; } + +.small-offset-2 { + margin-left: 16.66667%; } + +.small-4 { + width: 33.33333%; } + +.small-push-4 { + position: relative; + left: 33.33333%; } + +.small-pull-4 { + position: relative; + left: -33.33333%; } + +.small-offset-3 { + margin-left: 25%; } + +.small-5 { + width: 41.66667%; } + +.small-push-5 { + position: relative; + left: 41.66667%; } + +.small-pull-5 { + position: relative; + left: -41.66667%; } + +.small-offset-4 { + margin-left: 33.33333%; } + +.small-6 { + width: 50%; } + +.small-push-6 { + position: relative; + left: 50%; } + +.small-pull-6 { + position: relative; + left: -50%; } + +.small-offset-5 { + margin-left: 41.66667%; } + +.small-7 { + width: 58.33333%; } + +.small-push-7 { + position: relative; + left: 58.33333%; } + +.small-pull-7 { + position: relative; + left: -58.33333%; } + +.small-offset-6 { + margin-left: 50%; } + +.small-8 { + width: 66.66667%; } + +.small-push-8 { + position: relative; + left: 66.66667%; } + +.small-pull-8 { + position: relative; + left: -66.66667%; } + +.small-offset-7 { + margin-left: 58.33333%; } + +.small-9 { + width: 75%; } + +.small-push-9 { + position: relative; + left: 75%; } + +.small-pull-9 { + position: relative; + left: -75%; } + +.small-offset-8 { + margin-left: 66.66667%; } + +.small-10 { + width: 83.33333%; } + +.small-push-10 { + position: relative; + left: 83.33333%; } + +.small-pull-10 { + position: relative; + left: -83.33333%; } + +.small-offset-9 { + margin-left: 75%; } + +.small-11 { + width: 91.66667%; } + +.small-push-11 { + position: relative; + left: 91.66667%; } + +.small-pull-11 { + position: relative; + left: -91.66667%; } + +.small-offset-10 { + margin-left: 83.33333%; } + +.small-12 { + width: 100%; } + +.small-offset-11 { + margin-left: 91.66667%; } + +.small-up-1 > .column, .small-up-1 > .columns { + width: 100%; + float: left; } + .small-up-1 > .column:nth-of-type(1n), .small-up-1 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-1 > .column:nth-of-type(1n+1), .small-up-1 > .columns:nth-of-type(1n+1) { + clear: both; } + .small-up-1 > .column:last-child, .small-up-1 > .columns:last-child { + float: left; } + +.small-up-2 > .column, .small-up-2 > .columns { + width: 50%; + float: left; } + .small-up-2 > .column:nth-of-type(1n), .small-up-2 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-2 > .column:nth-of-type(2n+1), .small-up-2 > .columns:nth-of-type(2n+1) { + clear: both; } + .small-up-2 > .column:last-child, .small-up-2 > .columns:last-child { + float: left; } + +.small-up-3 > .column, .small-up-3 > .columns { + width: 33.33333%; + float: left; } + .small-up-3 > .column:nth-of-type(1n), .small-up-3 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-3 > .column:nth-of-type(3n+1), .small-up-3 > .columns:nth-of-type(3n+1) { + clear: both; } + .small-up-3 > .column:last-child, .small-up-3 > .columns:last-child { + float: left; } + +.small-up-4 > .column, .small-up-4 > .columns { + width: 25%; + float: left; } + .small-up-4 > .column:nth-of-type(1n), .small-up-4 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-4 > .column:nth-of-type(4n+1), .small-up-4 > .columns:nth-of-type(4n+1) { + clear: both; } + .small-up-4 > .column:last-child, .small-up-4 > .columns:last-child { + float: left; } + +.small-up-5 > .column, .small-up-5 > .columns { + width: 20%; + float: left; } + .small-up-5 > .column:nth-of-type(1n), .small-up-5 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-5 > .column:nth-of-type(5n+1), .small-up-5 > .columns:nth-of-type(5n+1) { + clear: both; } + .small-up-5 > .column:last-child, .small-up-5 > .columns:last-child { + float: left; } + +.small-up-6 > .column, .small-up-6 > .columns { + width: 16.66667%; + float: left; } + .small-up-6 > .column:nth-of-type(1n), .small-up-6 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-6 > .column:nth-of-type(6n+1), .small-up-6 > .columns:nth-of-type(6n+1) { + clear: both; } + .small-up-6 > .column:last-child, .small-up-6 > .columns:last-child { + float: left; } + +.small-up-7 > .column, .small-up-7 > .columns { + width: 14.28571%; + float: left; } + .small-up-7 > .column:nth-of-type(1n), .small-up-7 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-7 > .column:nth-of-type(7n+1), .small-up-7 > .columns:nth-of-type(7n+1) { + clear: both; } + .small-up-7 > .column:last-child, .small-up-7 > .columns:last-child { + float: left; } + +.small-up-8 > .column, .small-up-8 > .columns { + width: 12.5%; + float: left; } + .small-up-8 > .column:nth-of-type(1n), .small-up-8 > .columns:nth-of-type(1n) { + clear: none; } + .small-up-8 > .column:nth-of-type(8n+1), .small-up-8 > .columns:nth-of-type(8n+1) { + clear: both; } + .small-up-8 > .column:last-child, .small-up-8 > .columns:last-child { + float: left; } + +.small-collapse > .column, .small-collapse > .columns { + padding-left: 0; + padding-right: 0; } + +.small-collapse .row { + margin-left: 0; + margin-right: 0; } + +.expanded.row .small-collapse.row { + margin-left: 0; + margin-right: 0; } + +.small-uncollapse > .column, .small-uncollapse > .columns { + padding-left: 0.625rem; + padding-right: 0.625rem; } + +.small-centered { + margin-left: auto; + margin-right: auto; } + .small-centered, .small-centered:last-child:not(:first-child) { + float: none; + clear: both; } + +.small-uncentered, +.small-push-0, +.small-pull-0 { + position: static; + margin-left: 0; + margin-right: 0; + float: left; } + +@media screen and (min-width: 40em) { + .medium-1 { + width: 8.33333%; } + .medium-push-1 { + position: relative; + left: 8.33333%; } + .medium-pull-1 { + position: relative; + left: -8.33333%; } + .medium-offset-0 { + margin-left: 0%; } + .medium-2 { + width: 16.66667%; } + .medium-push-2 { + position: relative; + left: 16.66667%; } + .medium-pull-2 { + position: relative; + left: -16.66667%; } + .medium-offset-1 { + margin-left: 8.33333%; } + .medium-3 { + width: 25%; } + .medium-push-3 { + position: relative; + left: 25%; } + .medium-pull-3 { + position: relative; + left: -25%; } + .medium-offset-2 { + margin-left: 16.66667%; } + .medium-4 { + width: 33.33333%; } + .medium-push-4 { + position: relative; + left: 33.33333%; } + .medium-pull-4 { + position: relative; + left: -33.33333%; } + .medium-offset-3 { + margin-left: 25%; } + .medium-5 { + width: 41.66667%; } + .medium-push-5 { + position: relative; + left: 41.66667%; } + .medium-pull-5 { + position: relative; + left: -41.66667%; } + .medium-offset-4 { + margin-left: 33.33333%; } + .medium-6 { + width: 50%; } + .medium-push-6 { + position: relative; + left: 50%; } + .medium-pull-6 { + position: relative; + left: -50%; } + .medium-offset-5 { + margin-left: 41.66667%; } + .medium-7 { + width: 58.33333%; } + .medium-push-7 { + position: relative; + left: 58.33333%; } + .medium-pull-7 { + position: relative; + left: -58.33333%; } + .medium-offset-6 { + margin-left: 50%; } + .medium-8 { + width: 66.66667%; } + .medium-push-8 { + position: relative; + left: 66.66667%; } + .medium-pull-8 { + position: relative; + left: -66.66667%; } + .medium-offset-7 { + margin-left: 58.33333%; } + .medium-9 { + width: 75%; } + .medium-push-9 { + position: relative; + left: 75%; } + .medium-pull-9 { + position: relative; + left: -75%; } + .medium-offset-8 { + margin-left: 66.66667%; } + .medium-10 { + width: 83.33333%; } + .medium-push-10 { + position: relative; + left: 83.33333%; } + .medium-pull-10 { + position: relative; + left: -83.33333%; } + .medium-offset-9 { + margin-left: 75%; } + .medium-11 { + width: 91.66667%; } + .medium-push-11 { + position: relative; + left: 91.66667%; } + .medium-pull-11 { + position: relative; + left: -91.66667%; } + .medium-offset-10 { + margin-left: 83.33333%; } + .medium-12 { + width: 100%; } + .medium-offset-11 { + margin-left: 91.66667%; } + .medium-up-1 > .column, .medium-up-1 > .columns { + width: 100%; + float: left; } + .medium-up-1 > .column:nth-of-type(1n), .medium-up-1 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-1 > .column:nth-of-type(1n+1), .medium-up-1 > .columns:nth-of-type(1n+1) { + clear: both; } + .medium-up-1 > .column:last-child, .medium-up-1 > .columns:last-child { + float: left; } + .medium-up-2 > .column, .medium-up-2 > .columns { + width: 50%; + float: left; } + .medium-up-2 > .column:nth-of-type(1n), .medium-up-2 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-2 > .column:nth-of-type(2n+1), .medium-up-2 > .columns:nth-of-type(2n+1) { + clear: both; } + .medium-up-2 > .column:last-child, .medium-up-2 > .columns:last-child { + float: left; } + .medium-up-3 > .column, .medium-up-3 > .columns { + width: 33.33333%; + float: left; } + .medium-up-3 > .column:nth-of-type(1n), .medium-up-3 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-3 > .column:nth-of-type(3n+1), .medium-up-3 > .columns:nth-of-type(3n+1) { + clear: both; } + .medium-up-3 > .column:last-child, .medium-up-3 > .columns:last-child { + float: left; } + .medium-up-4 > .column, .medium-up-4 > .columns { + width: 25%; + float: left; } + .medium-up-4 > .column:nth-of-type(1n), .medium-up-4 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-4 > .column:nth-of-type(4n+1), .medium-up-4 > .columns:nth-of-type(4n+1) { + clear: both; } + .medium-up-4 > .column:last-child, .medium-up-4 > .columns:last-child { + float: left; } + .medium-up-5 > .column, .medium-up-5 > .columns { + width: 20%; + float: left; } + .medium-up-5 > .column:nth-of-type(1n), .medium-up-5 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-5 > .column:nth-of-type(5n+1), .medium-up-5 > .columns:nth-of-type(5n+1) { + clear: both; } + .medium-up-5 > .column:last-child, .medium-up-5 > .columns:last-child { + float: left; } + .medium-up-6 > .column, .medium-up-6 > .columns { + width: 16.66667%; + float: left; } + .medium-up-6 > .column:nth-of-type(1n), .medium-up-6 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-6 > .column:nth-of-type(6n+1), .medium-up-6 > .columns:nth-of-type(6n+1) { + clear: both; } + .medium-up-6 > .column:last-child, .medium-up-6 > .columns:last-child { + float: left; } + .medium-up-7 > .column, .medium-up-7 > .columns { + width: 14.28571%; + float: left; } + .medium-up-7 > .column:nth-of-type(1n), .medium-up-7 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-7 > .column:nth-of-type(7n+1), .medium-up-7 > .columns:nth-of-type(7n+1) { + clear: both; } + .medium-up-7 > .column:last-child, .medium-up-7 > .columns:last-child { + float: left; } + .medium-up-8 > .column, .medium-up-8 > .columns { + width: 12.5%; + float: left; } + .medium-up-8 > .column:nth-of-type(1n), .medium-up-8 > .columns:nth-of-type(1n) { + clear: none; } + .medium-up-8 > .column:nth-of-type(8n+1), .medium-up-8 > .columns:nth-of-type(8n+1) { + clear: both; } + .medium-up-8 > .column:last-child, .medium-up-8 > .columns:last-child { + float: left; } + .medium-collapse > .column, .medium-collapse > .columns { + padding-left: 0; + padding-right: 0; } + .medium-collapse .row { + margin-left: 0; + margin-right: 0; } + .expanded.row .medium-collapse.row { + margin-left: 0; + margin-right: 0; } + .medium-uncollapse > .column, .medium-uncollapse > .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } + .medium-centered { + margin-left: auto; + margin-right: auto; } + .medium-centered, .medium-centered:last-child:not(:first-child) { + float: none; + clear: both; } + .medium-uncentered, + .medium-push-0, + .medium-pull-0 { + position: static; + margin-left: 0; + margin-right: 0; + float: left; } } + +@media screen and (min-width: 64em) { + .large-1 { + width: 8.33333%; } + .large-push-1 { + position: relative; + left: 8.33333%; } + .large-pull-1 { + position: relative; + left: -8.33333%; } + .large-offset-0 { + margin-left: 0%; } + .large-2 { + width: 16.66667%; } + .large-push-2 { + position: relative; + left: 16.66667%; } + .large-pull-2 { + position: relative; + left: -16.66667%; } + .large-offset-1 { + margin-left: 8.33333%; } + .large-3 { + width: 25%; } + .large-push-3 { + position: relative; + left: 25%; } + .large-pull-3 { + position: relative; + left: -25%; } + .large-offset-2 { + margin-left: 16.66667%; } + .large-4 { + width: 33.33333%; } + .large-push-4 { + position: relative; + left: 33.33333%; } + .large-pull-4 { + position: relative; + left: -33.33333%; } + .large-offset-3 { + margin-left: 25%; } + .large-5 { + width: 41.66667%; } + .large-push-5 { + position: relative; + left: 41.66667%; } + .large-pull-5 { + position: relative; + left: -41.66667%; } + .large-offset-4 { + margin-left: 33.33333%; } + .large-6 { + width: 50%; } + .large-push-6 { + position: relative; + left: 50%; } + .large-pull-6 { + position: relative; + left: -50%; } + .large-offset-5 { + margin-left: 41.66667%; } + .large-7 { + width: 58.33333%; } + .large-push-7 { + position: relative; + left: 58.33333%; } + .large-pull-7 { + position: relative; + left: -58.33333%; } + .large-offset-6 { + margin-left: 50%; } + .large-8 { + width: 66.66667%; } + .large-push-8 { + position: relative; + left: 66.66667%; } + .large-pull-8 { + position: relative; + left: -66.66667%; } + .large-offset-7 { + margin-left: 58.33333%; } + .large-9 { + width: 75%; } + .large-push-9 { + position: relative; + left: 75%; } + .large-pull-9 { + position: relative; + left: -75%; } + .large-offset-8 { + margin-left: 66.66667%; } + .large-10 { + width: 83.33333%; } + .large-push-10 { + position: relative; + left: 83.33333%; } + .large-pull-10 { + position: relative; + left: -83.33333%; } + .large-offset-9 { + margin-left: 75%; } + .large-11 { + width: 91.66667%; } + .large-push-11 { + position: relative; + left: 91.66667%; } + .large-pull-11 { + position: relative; + left: -91.66667%; } + .large-offset-10 { + margin-left: 83.33333%; } + .large-12 { + width: 100%; } + .large-offset-11 { + margin-left: 91.66667%; } + .large-up-1 > .column, .large-up-1 > .columns { + width: 100%; + float: left; } + .large-up-1 > .column:nth-of-type(1n), .large-up-1 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-1 > .column:nth-of-type(1n+1), .large-up-1 > .columns:nth-of-type(1n+1) { + clear: both; } + .large-up-1 > .column:last-child, .large-up-1 > .columns:last-child { + float: left; } + .large-up-2 > .column, .large-up-2 > .columns { + width: 50%; + float: left; } + .large-up-2 > .column:nth-of-type(1n), .large-up-2 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-2 > .column:nth-of-type(2n+1), .large-up-2 > .columns:nth-of-type(2n+1) { + clear: both; } + .large-up-2 > .column:last-child, .large-up-2 > .columns:last-child { + float: left; } + .large-up-3 > .column, .large-up-3 > .columns { + width: 33.33333%; + float: left; } + .large-up-3 > .column:nth-of-type(1n), .large-up-3 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-3 > .column:nth-of-type(3n+1), .large-up-3 > .columns:nth-of-type(3n+1) { + clear: both; } + .large-up-3 > .column:last-child, .large-up-3 > .columns:last-child { + float: left; } + .large-up-4 > .column, .large-up-4 > .columns { + width: 25%; + float: left; } + .large-up-4 > .column:nth-of-type(1n), .large-up-4 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-4 > .column:nth-of-type(4n+1), .large-up-4 > .columns:nth-of-type(4n+1) { + clear: both; } + .large-up-4 > .column:last-child, .large-up-4 > .columns:last-child { + float: left; } + .large-up-5 > .column, .large-up-5 > .columns { + width: 20%; + float: left; } + .large-up-5 > .column:nth-of-type(1n), .large-up-5 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-5 > .column:nth-of-type(5n+1), .large-up-5 > .columns:nth-of-type(5n+1) { + clear: both; } + .large-up-5 > .column:last-child, .large-up-5 > .columns:last-child { + float: left; } + .large-up-6 > .column, .large-up-6 > .columns { + width: 16.66667%; + float: left; } + .large-up-6 > .column:nth-of-type(1n), .large-up-6 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-6 > .column:nth-of-type(6n+1), .large-up-6 > .columns:nth-of-type(6n+1) { + clear: both; } + .large-up-6 > .column:last-child, .large-up-6 > .columns:last-child { + float: left; } + .large-up-7 > .column, .large-up-7 > .columns { + width: 14.28571%; + float: left; } + .large-up-7 > .column:nth-of-type(1n), .large-up-7 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-7 > .column:nth-of-type(7n+1), .large-up-7 > .columns:nth-of-type(7n+1) { + clear: both; } + .large-up-7 > .column:last-child, .large-up-7 > .columns:last-child { + float: left; } + .large-up-8 > .column, .large-up-8 > .columns { + width: 12.5%; + float: left; } + .large-up-8 > .column:nth-of-type(1n), .large-up-8 > .columns:nth-of-type(1n) { + clear: none; } + .large-up-8 > .column:nth-of-type(8n+1), .large-up-8 > .columns:nth-of-type(8n+1) { + clear: both; } + .large-up-8 > .column:last-child, .large-up-8 > .columns:last-child { + float: left; } + .large-collapse > .column, .large-collapse > .columns { + padding-left: 0; + padding-right: 0; } + .large-collapse .row { + margin-left: 0; + margin-right: 0; } + .expanded.row .large-collapse.row { + margin-left: 0; + margin-right: 0; } + .large-uncollapse > .column, .large-uncollapse > .columns { + padding-left: 0.9375rem; + padding-right: 0.9375rem; } + .large-centered { + margin-left: auto; + margin-right: auto; } + .large-centered, .large-centered:last-child:not(:first-child) { + float: none; + clear: both; } + .large-uncentered, + .large-push-0, + .large-pull-0 { + position: static; + margin-left: 0; + margin-right: 0; + float: left; } } + +div, +dl, +dt, +dd, +ul, +ol, +li, +h1, +h2, +h3, +h4, +h5, +h6, +pre, +form, +p, +blockquote, +th, +td { + margin: 0; + padding: 0; } + +p { + font-size: inherit; + line-height: 1.6; + margin-bottom: 1rem; + text-rendering: optimizeLegibility; } + +em, +i { + font-style: italic; + line-height: inherit; } + +strong, +b { + font-weight: bold; + line-height: inherit; } + +small { + font-size: 80%; + line-height: inherit; } + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + font-style: normal; + color: inherit; + text-rendering: optimizeLegibility; + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.4; } + h1 small, + h2 small, + h3 small, + h4 small, + h5 small, + h6 small { + color: #cacaca; + line-height: 0; } + +h1 { + font-size: 1.5rem; } + +h2 { + font-size: 1.25rem; } + +h3 { + font-size: 1.1875rem; } + +h4 { + font-size: 1.125rem; } + +h5 { + font-size: 1.0625rem; } + +h6 { + font-size: 1rem; } + +@media screen and (min-width: 40em) { + h1 { + font-size: 3rem; } + h2 { + font-size: 2.5rem; } + h3 { + font-size: 1.9375rem; } + h4 { + font-size: 1.5625rem; } + h5 { + font-size: 1.25rem; } + h6 { + font-size: 1rem; } } + +a { + color: #2199e8; + text-decoration: none; + line-height: inherit; + cursor: pointer; } + a:hover, a:focus { + color: #1585cf; } + a img { + border: 0; } + +hr { + max-width: 75rem; + height: 0; + border-right: 0; + border-top: 0; + border-bottom: 1px solid #cacaca; + border-left: 0; + margin: 1.25rem auto; + clear: both; } + +ul, +ol, +dl { + line-height: 1.6; + margin-bottom: 1rem; + list-style-position: outside; } + +li { + font-size: inherit; } + +ul { + list-style-type: disc; + margin-left: 1.25rem; } + +ol { + margin-left: 1.25rem; } + +ul ul, ol ul, ul ol, ol ol { + margin-left: 1.25rem; + margin-bottom: 0; } + +dl { + margin-bottom: 1rem; } + dl dt { + margin-bottom: 0.3rem; + font-weight: bold; } + +blockquote { + margin: 0 0 1rem; + padding: 0.5625rem 1.25rem 0 1.1875rem; + border-left: 1px solid #cacaca; } + blockquote, blockquote p { + line-height: 1.6; + color: #8a8a8a; } + +cite { + display: block; + font-size: 0.8125rem; + color: #8a8a8a; } + cite:before { + content: '\2014 \0020'; } + +abbr { + color: #0a0a0a; + cursor: help; + border-bottom: 1px dotted #0a0a0a; } + +code { + font-family: Consolas, "Liberation Mono", Courier, monospace; + font-weight: normal; + color: #0a0a0a; + background-color: #e6e6e6; + border: 1px solid #cacaca; + padding: 0.125rem 0.3125rem 0.0625rem; } + +kbd { + padding: 0.125rem 0.25rem 0; + margin: 0; + background-color: #e6e6e6; + color: #0a0a0a; + font-family: Consolas, "Liberation Mono", Courier, monospace; } + +.subheader { + margin-top: 0.2rem; + margin-bottom: 0.5rem; + font-weight: normal; + line-height: 1.4; + color: #8a8a8a; } + +.lead { + font-size: 125%; + line-height: 1.6; } + +.stat { + font-size: 2.5rem; + line-height: 1; } + p + .stat { + margin-top: -1rem; } + +.no-bullet { + margin-left: 0; + list-style: none; } + +.text-left { + text-align: left; } + +.text-right { + text-align: right; } + +.text-center { + text-align: center; } + +.text-justify { + text-align: justify; } + +@media screen and (min-width: 40em) { + .medium-text-left { + text-align: left; } + .medium-text-right { + text-align: right; } + .medium-text-center { + text-align: center; } + .medium-text-justify { + text-align: justify; } } + +@media screen and (min-width: 64em) { + .large-text-left { + text-align: left; } + .large-text-right { + text-align: right; } + .large-text-center { + text-align: center; } + .large-text-justify { + text-align: justify; } } + +.show-for-print { + display: none !important; } + +@media print { + * { + background: transparent !important; + color: black !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; } + .show-for-print { + display: block !important; } + .hide-for-print { + display: none !important; } + table.show-for-print { + display: table !important; } + thead.show-for-print { + display: table-header-group !important; } + tbody.show-for-print { + display: table-row-group !important; } + tr.show-for-print { + display: table-row !important; } + td.show-for-print { + display: table-cell !important; } + th.show-for-print { + display: table-cell !important; } + a, + a:visited { + text-decoration: underline; } + a[href]:after { + content: " (" attr(href) ")"; } + .ir a:after, + a[href^='javascript:']:after, + a[href^='#']:after { + content: ''; } + abbr[title]:after { + content: " (" attr(title) ")"; } + pre, + blockquote { + border: 1px solid #8a8a8a; + page-break-inside: avoid; } + thead { + display: table-header-group; } + tr, + img { + page-break-inside: avoid; } + img { + max-width: 100% !important; } + @page { + margin: 0.5cm; } + p, + h2, + h3 { + orphans: 3; + widows: 3; } + h2, + h3 { + page-break-after: avoid; } } + +[type='text'], [type='password'], [type='date'], [type='datetime'], [type='datetime-local'], [type='month'], [type='week'], [type='email'], [type='number'], [type='search'], [type='tel'], [type='time'], [type='url'], [type='color'], +textarea { + display: block; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 2.4375rem; + padding: 0.5rem; + border: 1px solid #cacaca; + margin: 0 0 1rem; + font-family: inherit; + font-size: 1rem; + color: #0a0a0a; + background-color: #fefefe; + -webkit-box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + border-radius: 0; + -webkit-transition: -webkit-box-shadow 0.5s, border-color 0.25s ease-in-out; + transition: box-shadow 0.5s, border-color 0.25s ease-in-out; + -webkit-appearance: none; + -moz-appearance: none; } + [type='text']:focus, [type='password']:focus, [type='date']:focus, [type='datetime']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='week']:focus, [type='email']:focus, [type='number']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='url']:focus, [type='color']:focus, + textarea:focus { + border: 1px solid #8a8a8a; + background-color: #fefefe; + outline: none; + -webkit-box-shadow: 0 0 5px #cacaca; + box-shadow: 0 0 5px #cacaca; + -webkit-transition: -webkit-box-shadow 0.5s, border-color 0.25s ease-in-out; + transition: box-shadow 0.5s, border-color 0.25s ease-in-out; } + +textarea { + max-width: 100%; } + textarea[rows] { + height: auto; } + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #cacaca; } + +input::-moz-placeholder, +textarea::-moz-placeholder { + color: #cacaca; } + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #cacaca; } + +input::placeholder, +textarea::placeholder { + color: #cacaca; } + +input:disabled, input[readonly], +textarea:disabled, +textarea[readonly] { + background-color: #e6e6e6; + cursor: not-allowed; } + +[type='submit'], +[type='button'] { + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; } + +input[type='search'] { + -webkit-box-sizing: border-box; + box-sizing: border-box; } + +[type='file'], +[type='checkbox'], +[type='radio'] { + margin: 0 0 1rem; } + +[type='checkbox'] + label, +[type='radio'] + label { + display: inline-block; + margin-left: 0.5rem; + margin-right: 1rem; + margin-bottom: 0; + vertical-align: baseline; } + [type='checkbox'] + label[for], + [type='radio'] + label[for] { + cursor: pointer; } + +label > [type='checkbox'], +label > [type='radio'] { + margin-right: 0.5rem; } + +[type='file'] { + width: 100%; } + +label { + display: block; + margin: 0; + font-size: 0.875rem; + font-weight: normal; + line-height: 1.8; + color: #0a0a0a; } + label.middle { + margin: 0 0 1rem; + padding: 0.5625rem 0; } + +.help-text { + margin-top: -0.5rem; + font-size: 0.8125rem; + font-style: italic; + color: #0a0a0a; } + +.input-group { + display: table; + width: 100%; + margin-bottom: 1rem; } + .input-group > :first-child { + border-radius: 0 0 0 0; } + .input-group > :last-child > * { + border-radius: 0 0 0 0; } + +.input-group-label, .input-group-field, .input-group-button { + margin: 0; + white-space: nowrap; + display: table-cell; + vertical-align: middle; } + +.input-group-label { + text-align: center; + padding: 0 1rem; + background: #e6e6e6; + color: #0a0a0a; + border: 1px solid #cacaca; + white-space: nowrap; + width: 1%; + height: 100%; } + .input-group-label:first-child { + border-right: 0; } + .input-group-label:last-child { + border-left: 0; } + +.input-group-field { + border-radius: 0; + height: 2.5rem; } + +.input-group-button { + padding-top: 0; + padding-bottom: 0; + text-align: center; + height: 100%; + width: 1%; } + .input-group-button a, + .input-group-button input, + .input-group-button button { + margin: 0; } + +.input-group .input-group-button { + display: table-cell; } + +fieldset { + border: 0; + padding: 0; + margin: 0; } + +legend { + margin-bottom: 0.5rem; + max-width: 100%; } + +.fieldset { + border: 1px solid #cacaca; + padding: 1.25rem; + margin: 1.125rem 0; } + .fieldset legend { + background: #fefefe; + padding: 0 0.1875rem; + margin: 0; + margin-left: -0.1875rem; } + +select { + height: 2.4375rem; + padding: 0.5rem; + border: 1px solid #cacaca; + margin: 0 0 1rem; + font-size: 1rem; + font-family: inherit; + line-height: normal; + color: #0a0a0a; + background-color: #fefefe; + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + -webkit-background-size: 9px 6px; + background-size: 9px 6px; + background-position: right -1rem center; + -webkit-background-origin: content-box; + background-origin: content-box; + background-repeat: no-repeat; + padding-right: 1.5rem; } + @media screen and (min-width: 0\0) { + select { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg=="); } } + select:disabled { + background-color: #e6e6e6; + cursor: not-allowed; } + select::-ms-expand { + display: none; } + select[multiple] { + height: auto; + background-image: none; } + +.is-invalid-input:not(:focus) { + background-color: rgba(236, 88, 64, 0.1); + border-color: #ec5840; } + +.is-invalid-label { + color: #ec5840; } + +.form-error { + display: none; + margin-top: -0.5rem; + margin-bottom: 1rem; + font-size: 0.75rem; + font-weight: bold; + color: #ec5840; } + .form-error.is-visible { + display: block; } + +.button { + display: inline-block; + text-align: center; + line-height: 1; + cursor: pointer; + -webkit-appearance: none; + -webkit-transition: background-color 0.25s ease-out, color 0.25s ease-out; + transition: background-color 0.25s ease-out, color 0.25s ease-out; + vertical-align: middle; + border: 1px solid transparent; + border-radius: 0; + padding: 0.85em 1em; + margin: 0 0 1rem 0; + font-size: 0.9rem; + background-color: #2199e8; + color: #fefefe; } + [data-whatinput='mouse'] .button { + outline: 0; } + .button:hover, .button:focus { + background-color: #1583cc; + color: #fefefe; } + .button.tiny { + font-size: 0.6rem; } + .button.small { + font-size: 0.75rem; } + .button.large { + font-size: 1.25rem; } + .button.expanded { + display: block; + width: 100%; + margin-left: 0; + margin-right: 0; } + .button.primary { + background-color: #2199e8; + color: #fefefe; } + .button.primary:hover, .button.primary:focus { + background-color: #147cc0; + color: #fefefe; } + .button.secondary { + background-color: #777; + color: #fefefe; } + .button.secondary:hover, .button.secondary:focus { + background-color: #5f5f5f; + color: #fefefe; } + .button.success { + background-color: #3adb76; + color: #fefefe; } + .button.success:hover, .button.success:focus { + background-color: #22bb5b; + color: #fefefe; } + .button.warning { + background-color: #ffae00; + color: #fefefe; } + .button.warning:hover, .button.warning:focus { + background-color: #cc8b00; + color: #fefefe; } + .button.alert { + background-color: #ec5840; + color: #fefefe; } + .button.alert:hover, .button.alert:focus { + background-color: #da3116; + color: #fefefe; } + .button.hollow { + border: 1px solid #2199e8; + color: #2199e8; } + .button.hollow, .button.hollow:hover, .button.hollow:focus { + background-color: transparent; } + .button.hollow:hover, .button.hollow:focus { + border-color: #0c4d78; + color: #0c4d78; } + .button.hollow.primary { + border: 1px solid #2199e8; + color: #2199e8; } + .button.hollow.primary:hover, .button.hollow.primary:focus { + border-color: #0c4d78; + color: #0c4d78; } + .button.hollow.secondary { + border: 1px solid #777; + color: #777; } + .button.hollow.secondary:hover, .button.hollow.secondary:focus { + border-color: #3c3c3c; + color: #3c3c3c; } + .button.hollow.success { + border: 1px solid #3adb76; + color: #3adb76; } + .button.hollow.success:hover, .button.hollow.success:focus { + border-color: #157539; + color: #157539; } + .button.hollow.warning { + border: 1px solid #ffae00; + color: #ffae00; } + .button.hollow.warning:hover, .button.hollow.warning:focus { + border-color: #805700; + color: #805700; } + .button.hollow.alert { + border: 1px solid #ec5840; + color: #ec5840; } + .button.hollow.alert:hover, .button.hollow.alert:focus { + border-color: #881f0e; + color: #881f0e; } + .button.disabled, .button[disabled] { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus { + background-color: #2199e8; + color: #fefefe; } + .button.disabled.primary, .button[disabled].primary { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.primary:hover, .button.disabled.primary:focus, .button[disabled].primary:hover, .button[disabled].primary:focus { + background-color: #2199e8; + color: #fefefe; } + .button.disabled.secondary, .button[disabled].secondary { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus { + background-color: #777; + color: #fefefe; } + .button.disabled.success, .button[disabled].success { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus { + background-color: #3adb76; + color: #fefefe; } + .button.disabled.warning, .button[disabled].warning { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.warning:hover, .button.disabled.warning:focus, .button[disabled].warning:hover, .button[disabled].warning:focus { + background-color: #ffae00; + color: #fefefe; } + .button.disabled.alert, .button[disabled].alert { + opacity: 0.25; + cursor: not-allowed; } + .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus { + background-color: #ec5840; + color: #fefefe; } + .button.dropdown::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.4em; + border-color: #fefefe transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + position: relative; + top: 0.4em; + float: right; + margin-left: 1em; + display: inline-block; } + .button.arrow-only::after { + margin-left: 0; + float: none; + top: -0.1em; } + +.accordion { + list-style-type: none; + background: #fefefe; + margin-left: 0; } + +.accordion-item:first-child > :first-child { + border-radius: 0 0 0 0; } + +.accordion-item:last-child > :last-child { + border-radius: 0 0 0 0; } + +.accordion-title { + display: block; + padding: 1.25rem 1rem; + line-height: 1; + font-size: 0.75rem; + color: #2199e8; + position: relative; + border: 1px solid #e6e6e6; + border-bottom: 0; } + :last-child:not(.is-active) > .accordion-title { + border-radius: 0 0 0 0; + border-bottom: 1px solid #e6e6e6; } + .accordion-title:hover, .accordion-title:focus { + background-color: #e6e6e6; } + .accordion-title::before { + content: '+'; + position: absolute; + right: 1rem; + top: 50%; + margin-top: -0.5rem; } + .is-active > .accordion-title::before { + content: '–'; } + +.accordion-content { + padding: 1rem; + display: none; + border: 1px solid #e6e6e6; + border-bottom: 0; + background-color: #fefefe; + color: #0a0a0a; } + :last-child > .accordion-content:last-child { + border-bottom: 1px solid #e6e6e6; } + +.is-accordion-submenu-parent > a { + position: relative; } + .is-accordion-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + position: absolute; + top: 50%; + margin-top: -4px; + right: 1rem; } + +.is-accordion-submenu-parent[aria-expanded='true'] > a::after { + -webkit-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + -webkit-transform: scaleY(-1); + -ms-transform: scaleY(-1); + transform: scaleY(-1); } + +.badge { + display: inline-block; + padding: 0.3em; + min-width: 2.1em; + font-size: 0.6rem; + text-align: center; + border-radius: 50%; + background: #2199e8; + color: #fefefe; } + .badge.secondary { + background: #777; + color: #fefefe; } + .badge.success { + background: #3adb76; + color: #fefefe; } + .badge.warning { + background: #ffae00; + color: #fefefe; } + .badge.alert { + background: #ec5840; + color: #fefefe; } + +.breadcrumbs { + list-style: none; + margin: 0 0 1rem 0; } + .breadcrumbs::before, .breadcrumbs::after { + content: ' '; + display: table; } + .breadcrumbs::after { + clear: both; } + .breadcrumbs li { + float: left; + color: #0a0a0a; + font-size: 0.6875rem; + cursor: default; + text-transform: uppercase; } + .breadcrumbs li:not(:last-child)::after { + color: #cacaca; + content: "/"; + margin: 0 0.75rem; + position: relative; + top: 1px; + opacity: 1; } + .breadcrumbs a { + color: #2199e8; } + .breadcrumbs a:hover { + text-decoration: underline; } + .breadcrumbs .disabled { + color: #cacaca; + cursor: not-allowed; } + +.button-group { + margin-bottom: 1rem; + font-size: 0; } + .button-group::before, .button-group::after { + content: ' '; + display: table; } + .button-group::after { + clear: both; } + .button-group .button { + margin: 0; + margin-right: 1px; + margin-bottom: 1px; + font-size: 0.9rem; } + .button-group .button:last-child { + margin-right: 0; } + .button-group.tiny .button { + font-size: 0.6rem; } + .button-group.small .button { + font-size: 0.75rem; } + .button-group.large .button { + font-size: 1.25rem; } + .button-group.expanded { + margin-right: -1px; } + .button-group.expanded::before, .button-group.expanded::after { + display: none; } + .button-group.expanded .button:first-child:nth-last-child(2), .button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button { + display: inline-block; + width: calc(50% - 1px); + margin-right: 1px; } + .button-group.expanded .button:first-child:nth-last-child(2):last-child, .button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button:last-child { + margin-right: -6px; } + .button-group.expanded .button:first-child:nth-last-child(3), .button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button { + display: inline-block; + width: calc(33.33333% - 1px); + margin-right: 1px; } + .button-group.expanded .button:first-child:nth-last-child(3):last-child, .button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button:last-child { + margin-right: -6px; } + .button-group.expanded .button:first-child:nth-last-child(4), .button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button { + display: inline-block; + width: calc(25% - 1px); + margin-right: 1px; } + .button-group.expanded .button:first-child:nth-last-child(4):last-child, .button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button:last-child { + margin-right: -6px; } + .button-group.expanded .button:first-child:nth-last-child(5), .button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button { + display: inline-block; + width: calc(20% - 1px); + margin-right: 1px; } + .button-group.expanded .button:first-child:nth-last-child(5):last-child, .button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button:last-child { + margin-right: -6px; } + .button-group.expanded .button:first-child:nth-last-child(6), .button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button { + display: inline-block; + width: calc(16.66667% - 1px); + margin-right: 1px; } + .button-group.expanded .button:first-child:nth-last-child(6):last-child, .button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button:last-child { + margin-right: -6px; } + .button-group.primary .button { + background-color: #2199e8; + color: #fefefe; } + .button-group.primary .button:hover, .button-group.primary .button:focus { + background-color: #147cc0; + color: #fefefe; } + .button-group.secondary .button { + background-color: #777; + color: #fefefe; } + .button-group.secondary .button:hover, .button-group.secondary .button:focus { + background-color: #5f5f5f; + color: #fefefe; } + .button-group.success .button { + background-color: #3adb76; + color: #fefefe; } + .button-group.success .button:hover, .button-group.success .button:focus { + background-color: #22bb5b; + color: #fefefe; } + .button-group.warning .button { + background-color: #ffae00; + color: #fefefe; } + .button-group.warning .button:hover, .button-group.warning .button:focus { + background-color: #cc8b00; + color: #fefefe; } + .button-group.alert .button { + background-color: #ec5840; + color: #fefefe; } + .button-group.alert .button:hover, .button-group.alert .button:focus { + background-color: #da3116; + color: #fefefe; } + .button-group.stacked .button, .button-group.stacked-for-small .button, .button-group.stacked-for-medium .button { + width: 100%; } + .button-group.stacked .button:last-child, .button-group.stacked-for-small .button:last-child, .button-group.stacked-for-medium .button:last-child { + margin-bottom: 0; } + @media screen and (min-width: 40em) { + .button-group.stacked-for-small .button { + width: auto; + margin-bottom: 0; } } + @media screen and (min-width: 64em) { + .button-group.stacked-for-medium .button { + width: auto; + margin-bottom: 0; } } + @media screen and (max-width: 39.9375em) { + .button-group.stacked-for-small.expanded { + display: block; } + .button-group.stacked-for-small.expanded .button { + display: block; + margin-right: 0; } } + +.callout { + margin: 0 0 1rem 0; + padding: 1rem; + border: 1px solid rgba(10, 10, 10, 0.25); + border-radius: 0; + position: relative; + color: #0a0a0a; + background-color: white; } + .callout > :first-child { + margin-top: 0; } + .callout > :last-child { + margin-bottom: 0; } + .callout.primary { + background-color: #def0fc; } + .callout.secondary { + background-color: #ebebeb; } + .callout.success { + background-color: #e1faea; } + .callout.warning { + background-color: #fff3d9; } + .callout.alert { + background-color: #fce6e2; } + .callout.small { + padding-top: 0.5rem; + padding-right: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.5rem; } + .callout.large { + padding-top: 3rem; + padding-right: 3rem; + padding-bottom: 3rem; + padding-left: 3rem; } + +.close-button { + position: absolute; + color: #8a8a8a; + right: 1rem; + top: 0.5rem; + font-size: 2em; + line-height: 1; + cursor: pointer; } + [data-whatinput='mouse'] .close-button { + outline: 0; } + .close-button:hover, .close-button:focus { + color: #0a0a0a; } + +.menu { + margin: 0; + list-style-type: none; } + .menu > li { + display: table-cell; + vertical-align: middle; } + [data-whatinput='mouse'] .menu > li { + outline: 0; } + .menu > li > a { + display: block; + padding: 0.7rem 1rem; + line-height: 1; } + .menu input, + .menu a, + .menu button { + margin-bottom: 0; } + .menu > li > a img, + .menu > li > a i, + .menu > li > a svg { + vertical-align: middle; } + .menu > li > a img + span, + .menu > li > a i + span, + .menu > li > a svg + span { + vertical-align: middle; } + .menu > li > a img, + .menu > li > a i, + .menu > li > a svg { + margin-right: 0.25rem; + display: inline-block; } + .menu > li { + display: table-cell; } + .menu.vertical > li { + display: block; } + @media screen and (min-width: 40em) { + .menu.medium-horizontal > li { + display: table-cell; } + .menu.medium-vertical > li { + display: block; } } + @media screen and (min-width: 64em) { + .menu.large-horizontal > li { + display: table-cell; } + .menu.large-vertical > li { + display: block; } } + .menu.simple li { + line-height: 1; + display: inline-block; + margin-right: 1rem; } + .menu.simple a { + padding: 0; } + .menu.align-right::before, .menu.align-right::after { + content: ' '; + display: table; } + .menu.align-right::after { + clear: both; } + .menu.align-right > li { + float: right; } + .menu.expanded { + width: 100%; + display: table; + table-layout: fixed; } + .menu.expanded > li:first-child:last-child { + width: 100%; } + .menu.icon-top > li > a { + text-align: center; } + .menu.icon-top > li > a img, + .menu.icon-top > li > a i, + .menu.icon-top > li > a svg { + display: block; + margin: 0 auto 0.25rem; } + .menu.nested { + margin-left: 1rem; } + .menu .active > a { + color: #fefefe; + background: #2199e8; } + +.menu-text { + font-weight: bold; + color: inherit; + line-height: 1; + padding-top: 0; + padding-bottom: 0; + padding: 0.7rem 1rem; } + +.menu-centered { + text-align: center; } + .menu-centered > .menu { + display: inline-block; } + +.no-js [data-responsive-menu] ul { + display: none; } + +.menu-icon { + position: relative; + display: inline-block; + vertical-align: middle; + cursor: pointer; + width: 20px; + height: 16px; } + .menu-icon::after { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 2px; + background: #fefefe; + top: 0; + left: 0; + -webkit-box-shadow: 0 7px 0 #fefefe, 0 14px 0 #fefefe; + box-shadow: 0 7px 0 #fefefe, 0 14px 0 #fefefe; } + .menu-icon:hover::after { + background: #cacaca; + -webkit-box-shadow: 0 7px 0 #cacaca, 0 14px 0 #cacaca; + box-shadow: 0 7px 0 #cacaca, 0 14px 0 #cacaca; } + +.menu-icon.dark { + position: relative; + display: inline-block; + vertical-align: middle; + cursor: pointer; + width: 20px; + height: 16px; } + .menu-icon.dark::after { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 2px; + background: #0a0a0a; + top: 0; + left: 0; + -webkit-box-shadow: 0 7px 0 #0a0a0a, 0 14px 0 #0a0a0a; + box-shadow: 0 7px 0 #0a0a0a, 0 14px 0 #0a0a0a; } + .menu-icon.dark:hover::after { + background: #8a8a8a; + -webkit-box-shadow: 0 7px 0 #8a8a8a, 0 14px 0 #8a8a8a; + box-shadow: 0 7px 0 #8a8a8a, 0 14px 0 #8a8a8a; } + +.is-drilldown { + position: relative; + overflow: hidden; } + .is-drilldown li { + display: block !important; } + +.is-drilldown-submenu { + position: absolute; + top: 0; + left: 100%; + z-index: -1; + width: 100%; + background: #fefefe; + -webkit-transition: -webkit-transform 0.15s linear; + transition: transform 0.15s linear; } + .is-drilldown-submenu.is-active { + z-index: 1; + display: block; + -webkit-transform: translateX(-100%); + -ms-transform: translateX(-100%); + transform: translateX(-100%); } + .is-drilldown-submenu.is-closing { + -webkit-transform: translateX(100%); + -ms-transform: translateX(100%); + transform: translateX(100%); } + +.is-drilldown-submenu-parent > a { + position: relative; } + .is-drilldown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; + position: absolute; + top: 50%; + margin-top: -6px; + right: 1rem; } + +.js-drilldown-back > a::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 6px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; + border-left-width: 0; + display: inline-block; + vertical-align: middle; + margin-right: 0.75rem; } + +.dropdown-pane { + background-color: #fefefe; + border: 1px solid #cacaca; + border-radius: 0; + display: block; + font-size: 1rem; + padding: 1rem; + position: absolute; + visibility: hidden; + width: 300px; + z-index: 10; } + .dropdown-pane.is-open { + visibility: visible; } + +.dropdown-pane.tiny { + width: 100px; } + +.dropdown-pane.small { + width: 200px; } + +.dropdown-pane.large { + width: 400px; } + +.dropdown.menu > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + +.dropdown.menu > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + +.dropdown.menu > li.is-dropdown-submenu-parent > a { + padding-right: 1.5rem; + position: relative; } + +.dropdown.menu > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + right: 5px; + margin-top: -2px; } + +[data-whatinput='mouse'] .dropdown.menu a { + outline: 0; } + +.no-js .dropdown.menu ul { + display: none; } + +.dropdown.menu.vertical > li .is-dropdown-submenu { + top: 0; } + +.dropdown.menu.vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + +.dropdown.menu.vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + +.dropdown.menu.vertical > li > a::after { + right: 14px; + margin-top: -3px; } + +.dropdown.menu.vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + +.dropdown.menu.vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } + +@media screen and (min-width: 40em) { + .dropdown.menu.medium-horizontal > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + .dropdown.menu.medium-horizontal > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a { + padding-right: 1.5rem; + position: relative; } + .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + right: 5px; + margin-top: -2px; } + .dropdown.menu.medium-vertical > li .is-dropdown-submenu { + top: 0; } + .dropdown.menu.medium-vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .dropdown.menu.medium-vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + .dropdown.menu.medium-vertical > li > a::after { + right: 14px; + margin-top: -3px; } + .dropdown.menu.medium-vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .dropdown.menu.medium-vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } } + +@media screen and (min-width: 64em) { + .dropdown.menu.large-horizontal > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 0; + top: 100%; } + .dropdown.menu.large-horizontal > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 0; + top: 100%; } + .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a { + padding-right: 1.5rem; + position: relative; } + .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: #2199e8 transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + right: 5px; + margin-top: -2px; } + .dropdown.menu.large-vertical > li .is-dropdown-submenu { + top: 0; } + .dropdown.menu.large-vertical > li.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .dropdown.menu.large-vertical > li.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + .dropdown.menu.large-vertical > li > a::after { + right: 14px; + margin-top: -3px; } + .dropdown.menu.large-vertical > li.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .dropdown.menu.large-vertical > li.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } } + +.dropdown.menu.align-right .is-dropdown-submenu.first-sub { + top: 100%; + left: auto; + right: 0; } + +.is-dropdown-menu.vertical { + width: 100px; } + .is-dropdown-menu.vertical.align-right { + float: right; } + +.is-dropdown-submenu-parent { + position: relative; } + .is-dropdown-submenu-parent a::after { + position: absolute; + top: 50%; + right: 5px; + margin-top: -2px; } + .is-dropdown-submenu-parent.opens-inner > .is-dropdown-submenu { + top: 100%; + left: auto; } + .is-dropdown-submenu-parent.opens-left > .is-dropdown-submenu { + left: auto; + right: 100%; } + .is-dropdown-submenu-parent.opens-right > .is-dropdown-submenu { + right: auto; + left: 100%; } + +.is-dropdown-submenu { + display: none; + position: absolute; + top: 0; + left: 100%; + min-width: 200px; + z-index: 1; + background: #fefefe; + border: 1px solid #cacaca; } + .is-dropdown-submenu .is-dropdown-submenu-parent > a::after { + right: 14px; + margin-top: -3px; } + .is-dropdown-submenu .is-dropdown-submenu-parent.opens-left > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent #2199e8 transparent transparent; + border-right-style: solid; + border-left-width: 0; } + .is-dropdown-submenu .is-dropdown-submenu-parent.opens-right > a::after { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 5px; + border-color: transparent transparent transparent #2199e8; + border-left-style: solid; + border-right-width: 0; } + .is-dropdown-submenu .is-dropdown-submenu { + margin-top: -1px; } + .is-dropdown-submenu > li { + width: 100%; } + .is-dropdown-submenu.js-dropdown-active { + display: block; } + +.flex-video { + position: relative; + height: 0; + padding-bottom: 75%; + margin-bottom: 1rem; + overflow: hidden; } + .flex-video iframe, + .flex-video object, + .flex-video embed, + .flex-video video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; } + .flex-video.widescreen { + padding-bottom: 56.25%; } + .flex-video.vimeo { + padding-top: 0; } + +.label { + display: inline-block; + padding: 0.33333rem 0.5rem; + font-size: 0.8rem; + line-height: 1; + white-space: nowrap; + cursor: default; + border-radius: 0; + background: #2199e8; + color: #fefefe; } + .label.secondary { + background: #777; + color: #fefefe; } + .label.success { + background: #3adb76; + color: #fefefe; } + .label.warning { + background: #ffae00; + color: #fefefe; } + .label.alert { + background: #ec5840; + color: #fefefe; } + +.media-object { + margin-bottom: 1rem; + display: block; } + .media-object img { + max-width: none; } + @media screen and (max-width: 39.9375em) { + .media-object.stack-for-small .media-object-section { + padding: 0; + padding-bottom: 1rem; + display: block; } + .media-object.stack-for-small .media-object-section img { + width: 100%; } } + +.media-object-section { + display: table-cell; + vertical-align: top; } + .media-object-section:first-child { + padding-right: 1rem; } + .media-object-section:last-child:not(:nth-child(2)) { + padding-left: 1rem; } + .media-object-section > :last-child { + margin-bottom: 0; } + .media-object-section.middle { + vertical-align: middle; } + .media-object-section.bottom { + vertical-align: bottom; } + +html, +body { + height: 100%; } + +.off-canvas-wrapper { + width: 100%; + overflow-x: hidden; + position: relative; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-overflow-scrolling: auto; } + +.off-canvas-wrapper-inner { + position: relative; + width: 100%; + min-height: 100%; + -webkit-transition: -webkit-transform 0.5s ease; + transition: transform 0.5s ease; } + .off-canvas-wrapper-inner::before, .off-canvas-wrapper-inner::after { + content: ' '; + display: table; } + .off-canvas-wrapper-inner::after { + clear: both; } + +.off-canvas-content, +.off-canvas-content { + min-height: 100%; + background: #fefefe; + -webkit-transition: -webkit-transform 0.5s ease; + transition: transform 0.5s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + z-index: 1; + padding-bottom: 0.1px; + -webkit-box-shadow: 0 0 10px rgba(10, 10, 10, 0.5); + box-shadow: 0 0 10px rgba(10, 10, 10, 0.5); } + +.js-off-canvas-exit { + display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(254, 254, 254, 0.25); + cursor: pointer; + -webkit-transition: background 0.5s ease; + transition: background 0.5s ease; } + +.off-canvas { + position: absolute; + background: #e6e6e6; + z-index: -1; + max-height: 100%; + overflow-y: auto; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); } + [data-whatinput='mouse'] .off-canvas { + outline: 0; } + .off-canvas.position-left { + left: -250px; + top: 0; + width: 250px; } + .is-open-left { + -webkit-transform: translateX(250px); + -ms-transform: translateX(250px); + transform: translateX(250px); } + .off-canvas.position-right { + right: -250px; + top: 0; + width: 250px; } + .is-open-right { + -webkit-transform: translateX(-250px); + -ms-transform: translateX(-250px); + transform: translateX(-250px); } + +@media screen and (min-width: 40em) { + .position-left.reveal-for-medium { + left: 0; + z-index: auto; + position: fixed; } + .position-left.reveal-for-medium ~ .off-canvas-content { + margin-left: 250px; } + .position-right.reveal-for-medium { + right: 0; + z-index: auto; + position: fixed; } + .position-right.reveal-for-medium ~ .off-canvas-content { + margin-right: 250px; } } + +@media screen and (min-width: 64em) { + .position-left.reveal-for-large { + left: 0; + z-index: auto; + position: fixed; } + .position-left.reveal-for-large ~ .off-canvas-content { + margin-left: 250px; } + .position-right.reveal-for-large { + right: 0; + z-index: auto; + position: fixed; } + .position-right.reveal-for-large ~ .off-canvas-content { + margin-right: 250px; } } + +.orbit { + position: relative; } + +.orbit-container { + position: relative; + margin: 0; + overflow: hidden; + list-style: none; } + +.orbit-slide { + width: 100%; + max-height: 100%; } + .orbit-slide.no-motionui.is-active { + top: 0; + left: 0; } + +.orbit-figure { + margin: 0; } + +.orbit-image { + margin: 0; + width: 100%; + max-width: 100%; } + +.orbit-caption { + position: absolute; + bottom: 0; + width: 100%; + padding: 1rem; + margin-bottom: 0; + color: #fefefe; + background-color: rgba(10, 10, 10, 0.5); } + +.orbit-previous, .orbit-next { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + z-index: 10; + padding: 1rem; + color: #fefefe; } + [data-whatinput='mouse'] .orbit-previous, [data-whatinput='mouse'] .orbit-next { + outline: 0; } + .orbit-previous:hover, .orbit-next:hover, .orbit-previous:active, .orbit-next:active, .orbit-previous:focus, .orbit-next:focus { + background-color: rgba(10, 10, 10, 0.5); } + +.orbit-previous { + left: 0; } + +.orbit-next { + left: auto; + right: 0; } + +.orbit-bullets { + position: relative; + margin-top: 0.8rem; + margin-bottom: 0.8rem; + text-align: center; } + [data-whatinput='mouse'] .orbit-bullets { + outline: 0; } + .orbit-bullets button { + width: 1.2rem; + height: 1.2rem; + margin: 0.1rem; + background-color: #cacaca; + border-radius: 50%; } + .orbit-bullets button:hover { + background-color: #8a8a8a; } + .orbit-bullets button.is-active { + background-color: #8a8a8a; } + +.pagination { + margin-left: 0; + margin-bottom: 1rem; } + .pagination::before, .pagination::after { + content: ' '; + display: table; } + .pagination::after { + clear: both; } + .pagination li { + font-size: 0.875rem; + margin-right: 0.0625rem; + border-radius: 0; + display: none; } + .pagination li:last-child, .pagination li:first-child { + display: inline-block; } + @media screen and (min-width: 40em) { + .pagination li { + display: inline-block; } } + .pagination a, + .pagination button { + color: #0a0a0a; + display: block; + padding: 0.1875rem 0.625rem; + border-radius: 0; } + .pagination a:hover, + .pagination button:hover { + background: #e6e6e6; } + .pagination .current { + padding: 0.1875rem 0.625rem; + background: #2199e8; + color: #fefefe; + cursor: default; } + .pagination .disabled { + padding: 0.1875rem 0.625rem; + color: #cacaca; + cursor: not-allowed; } + .pagination .disabled:hover { + background: transparent; } + .pagination .ellipsis::after { + content: '\2026'; + padding: 0.1875rem 0.625rem; + color: #0a0a0a; } + +.pagination-previous a::before, +.pagination-previous.disabled::before { + content: '\00ab'; + display: inline-block; + margin-right: 0.5rem; } + +.pagination-next a::after, +.pagination-next.disabled::after { + content: '\00bb'; + display: inline-block; + margin-left: 0.5rem; } + +.progress { + background-color: #cacaca; + height: 1rem; + margin-bottom: 1rem; + border-radius: 0; } + .progress.primary .progress-meter { + background-color: #2199e8; } + .progress.secondary .progress-meter { + background-color: #777; } + .progress.success .progress-meter { + background-color: #3adb76; } + .progress.warning .progress-meter { + background-color: #ffae00; } + .progress.alert .progress-meter { + background-color: #ec5840; } + +.progress-meter { + position: relative; + display: block; + width: 0%; + height: 100%; + background-color: #2199e8; } + +.progress-meter-text { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + position: absolute; + margin: 0; + font-size: 0.75rem; + font-weight: bold; + color: #fefefe; + white-space: nowrap; } + +.slider { + position: relative; + height: 0.5rem; + margin-top: 1.25rem; + margin-bottom: 2.25rem; + background-color: #e6e6e6; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -ms-touch-action: none; + touch-action: none; } + +.slider-fill { + position: absolute; + top: 0; + left: 0; + display: inline-block; + max-width: 100%; + height: 0.5rem; + background-color: #cacaca; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + .slider-fill.is-dragging { + -webkit-transition: all 0s linear; + transition: all 0s linear; } + +.slider-handle { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + position: absolute; + left: 0; + z-index: 1; + display: inline-block; + width: 1.4rem; + height: 1.4rem; + background-color: #2199e8; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -ms-touch-action: manipulation; + touch-action: manipulation; + border-radius: 0; } + [data-whatinput='mouse'] .slider-handle { + outline: 0; } + .slider-handle:hover { + background-color: #1583cc; } + .slider-handle.is-dragging { + -webkit-transition: all 0s linear; + transition: all 0s linear; } + +.slider.disabled, +.slider[disabled] { + opacity: 0.25; + cursor: not-allowed; } + +.slider.vertical { + display: inline-block; + width: 0.5rem; + height: 12.5rem; + margin: 0 1.25rem; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); } + .slider.vertical .slider-fill { + top: 0; + width: 0.5rem; + max-height: 100%; } + .slider.vertical .slider-handle { + position: absolute; + top: 0; + left: 50%; + width: 1.4rem; + height: 1.4rem; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + +.sticky-container { + position: relative; } + +.sticky { + position: absolute; + z-index: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.sticky.is-stuck { + position: fixed; + z-index: 5; } + .sticky.is-stuck.is-at-top { + top: 0; } + .sticky.is-stuck.is-at-bottom { + bottom: 0; } + +.sticky.is-anchored { + position: absolute; + left: auto; + right: auto; } + .sticky.is-anchored.is-at-bottom { + bottom: 0; } + +body.is-reveal-open { + overflow: hidden; } + +html.is-reveal-open, +html.is-reveal-open body { + min-height: 100%; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +.reveal-overlay { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1005; + background-color: rgba(10, 10, 10, 0.45); + overflow-y: scroll; } + +.reveal { + display: none; + z-index: 1006; + padding: 1rem; + border: 1px solid #cacaca; + background-color: #fefefe; + border-radius: 0; + position: relative; + top: 100px; + margin-left: auto; + margin-right: auto; + overflow-y: auto; } + [data-whatinput='mouse'] .reveal { + outline: 0; } + @media screen and (min-width: 40em) { + .reveal { + min-height: 0; } } + .reveal .column, .reveal .columns, + .reveal .columns { + min-width: 0; } + .reveal > :last-child { + margin-bottom: 0; } + @media screen and (min-width: 40em) { + .reveal { + width: 600px; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal .reveal { + left: auto; + right: auto; + margin: 0 auto; } } + .reveal.collapse { + padding: 0; } + @media screen and (min-width: 40em) { + .reveal.tiny { + width: 30%; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal.small { + width: 50%; + max-width: 75rem; } } + @media screen and (min-width: 40em) { + .reveal.large { + width: 90%; + max-width: 75rem; } } + .reveal.full { + top: 0; + left: 0; + width: 100%; + height: 100%; + height: 100vh; + min-height: 100vh; + max-width: none; + margin-left: 0; + border: 0; + border-radius: 0; } + @media screen and (max-width: 39.9375em) { + .reveal { + top: 0; + left: 0; + width: 100%; + height: 100%; + height: 100vh; + min-height: 100vh; + max-width: none; + margin-left: 0; + border: 0; + border-radius: 0; } } + .reveal.without-overlay { + position: fixed; } + +.switch { + height: 2rem; + margin-bottom: 1rem; + outline: 0; + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + color: #fefefe; + font-weight: bold; + font-size: 0.875rem; } + +.switch-input { + opacity: 0; + position: absolute; + margin-bottom: 0; } + +.switch-paddle { + background: #cacaca; + cursor: pointer; + display: block; + position: relative; + width: 4rem; + height: 2rem; + -webkit-transition: all 0.25s ease-out; + transition: all 0.25s ease-out; + border-radius: 0; + color: inherit; + font-weight: inherit; } + input + .switch-paddle { + margin: 0; } + .switch-paddle::after { + background: #fefefe; + content: ''; + display: block; + position: absolute; + height: 1.5rem; + left: 0.25rem; + top: 0.25rem; + width: 1.5rem; + -webkit-transition: all 0.25s ease-out; + transition: all 0.25s ease-out; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + border-radius: 0; } + input:checked ~ .switch-paddle { + background: #2199e8; } + input:checked ~ .switch-paddle::after { + left: 2.25rem; } + [data-whatinput='mouse'] input:focus ~ .switch-paddle { + outline: 0; } + +.switch-active, .switch-inactive { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.switch-active { + left: 8%; + display: none; } + input:checked + label > .switch-active { + display: block; } + +.switch-inactive { + right: 15%; } + input:checked + label > .switch-inactive { + display: none; } + +.switch.tiny { + height: 1.5rem; } + .switch.tiny .switch-paddle { + width: 3rem; + height: 1.5rem; + font-size: 0.625rem; } + .switch.tiny .switch-paddle::after { + width: 1rem; + height: 1rem; } + .switch.tiny input:checked ~ .switch-paddle::after { + left: 1.75rem; } + +.switch.small { + height: 1.75rem; } + .switch.small .switch-paddle { + width: 3.5rem; + height: 1.75rem; + font-size: 0.75rem; } + .switch.small .switch-paddle::after { + width: 1.25rem; + height: 1.25rem; } + .switch.small input:checked ~ .switch-paddle::after { + left: 2rem; } + +.switch.large { + height: 2.5rem; } + .switch.large .switch-paddle { + width: 5rem; + height: 2.5rem; + font-size: 1rem; } + .switch.large .switch-paddle::after { + width: 2rem; + height: 2rem; } + .switch.large input:checked ~ .switch-paddle::after { + left: 2.75rem; } + +table { + width: 100%; + margin-bottom: 1rem; + border-radius: 0; } + table thead, + table tbody, + table tfoot { + border: 1px solid #f1f1f1; + background-color: #fefefe; } + table caption { + font-weight: bold; + padding: 0.5rem 0.625rem 0.625rem; } + table thead { + background: #f8f8f8; + color: #0a0a0a; } + table tfoot { + background: #f1f1f1; + color: #0a0a0a; } + table thead tr, + table tfoot tr { + background: transparent; } + table thead th, + table thead td, + table tfoot th, + table tfoot td { + padding: 0.5rem 0.625rem 0.625rem; + font-weight: bold; + text-align: left; } + table tbody tr:nth-child(even) { + background-color: #f1f1f1; } + table tbody th, + table tbody td { + padding: 0.5rem 0.625rem 0.625rem; } + +@media screen and (max-width: 63.9375em) { + table.stack thead { + display: none; } + table.stack tfoot { + display: none; } + table.stack tr, + table.stack th, + table.stack td { + display: block; } + table.stack td { + border-top: 0; } } + +table.scroll { + display: block; + width: 100%; + overflow-x: auto; } + +table.hover thead tr:hover { + background-color: #f3f3f3; } + +table.hover tfoot tr:hover { + background-color: #ececec; } + +table.hover tbody tr:hover { + background-color: #f9f9f9; } + +table.hover tbody tr:nth-of-type(even):hover { + background-color: #ececec; } + +.table-scroll { + overflow-x: auto; } + .table-scroll table { + width: auto; } + +.tabs { + margin: 0; + list-style-type: none; + background: #fefefe; + border: 1px solid #e6e6e6; } + .tabs::before, .tabs::after { + content: ' '; + display: table; } + .tabs::after { + clear: both; } + +.tabs.vertical > li { + width: auto; + float: none; + display: block; } + +.tabs.simple > li > a { + padding: 0; } + .tabs.simple > li > a:hover { + background: transparent; } + +.tabs.primary { + background: #2199e8; } + .tabs.primary > li > a { + color: #fefefe; } + .tabs.primary > li > a:hover, .tabs.primary > li > a:focus { + background: #1893e4; } + +.tabs-title { + float: left; } + .tabs-title > a { + display: block; + padding: 1.25rem 1.5rem; + line-height: 1; + font-size: 0.75rem; } + .tabs-title > a:hover { + background: #fefefe; } + .tabs-title > a:focus, .tabs-title > a[aria-selected='true'] { + background: #e6e6e6; } + +.tabs-content { + background: #fefefe; + -webkit-transition: all 0.5s ease; + transition: all 0.5s ease; + border: 1px solid #e6e6e6; + border-top: 0; } + +.tabs-content.vertical { + border: 1px solid #e6e6e6; + border-left: 0; } + +.tabs-panel { + display: none; + padding: 1rem; } + .tabs-panel.is-active { + display: block; } + +.thumbnail { + border: solid 4px #fefefe; + -webkit-box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2); + box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2); + display: inline-block; + line-height: 0; + max-width: 100%; + -webkit-transition: -webkit-box-shadow 200ms ease-out; + transition: box-shadow 200ms ease-out; + border-radius: 0; + margin-bottom: 1rem; } + .thumbnail:hover, .thumbnail:focus { + -webkit-box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); + box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); } + +.title-bar { + background: #0a0a0a; + color: #fefefe; + padding: 0.5rem; } + .title-bar::before, .title-bar::after { + content: ' '; + display: table; } + .title-bar::after { + clear: both; } + .title-bar .menu-icon { + margin-left: 0.25rem; + margin-right: 0.25rem; } + +.title-bar-left { + float: left; } + +.title-bar-right { + float: right; + text-align: right; } + +.title-bar-title { + font-weight: bold; + vertical-align: middle; + display: inline-block; } + +.has-tip { + border-bottom: dotted 1px #8a8a8a; + font-weight: bold; + position: relative; + display: inline-block; + cursor: help; } + +.tooltip { + background-color: #0a0a0a; + color: #fefefe; + font-size: 80%; + padding: 0.75rem; + position: absolute; + z-index: 10; + top: calc(100% + 0.6495rem); + max-width: 10rem !important; + border-radius: 0; } + .tooltip::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent transparent #0a0a0a; + border-bottom-style: solid; + border-top-width: 0; + bottom: 100%; + position: absolute; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + .tooltip.top::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: #0a0a0a transparent transparent; + border-top-style: solid; + border-bottom-width: 0; + top: 100%; + bottom: auto; } + .tooltip.left::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent transparent transparent #0a0a0a; + border-left-style: solid; + border-right-width: 0; + bottom: auto; + left: 100%; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .tooltip.right::before { + content: ''; + display: block; + width: 0; + height: 0; + border: inset 0.75rem; + border-color: transparent #0a0a0a transparent transparent; + border-right-style: solid; + border-left-width: 0; + bottom: auto; + left: auto; + right: 100%; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.top-bar { + padding: 0.5rem; } + .top-bar::before, .top-bar::after { + content: ' '; + display: table; } + .top-bar::after { + clear: both; } + .top-bar, + .top-bar ul { + background-color: #e6e6e6; } + .top-bar input { + max-width: 200px; + margin-right: 1rem; } + .top-bar .input-group-field { + width: 100%; + margin-right: 0; } + .top-bar input.button { + width: auto; } + .top-bar .top-bar-left, + .top-bar .top-bar-right { + width: 100%; } + @media screen and (min-width: 40em) { + .top-bar .top-bar-left, + .top-bar .top-bar-right { + width: auto; } } + @media screen and (max-width: 63.9375em) { + .top-bar.stacked-for-medium .top-bar-left, + .top-bar.stacked-for-medium .top-bar-right { + width: 100%; } } + @media screen and (max-width: 74.9375em) { + .top-bar.stacked-for-large .top-bar-left, + .top-bar.stacked-for-large .top-bar-right { + width: 100%; } } + +.top-bar-title { + float: left; + margin-right: 1rem; } + +.top-bar-left { + float: left; } + +.top-bar-right { + float: right; } + +.hide { + display: none !important; } + +.invisible { + visibility: hidden; } + +@media screen and (max-width: 39.9375em) { + .hide-for-small-only { + display: none !important; } } + +@media screen and (max-width: 0em), screen and (min-width: 40em) { + .show-for-small-only { + display: none !important; } } + +@media screen and (min-width: 40em) { + .hide-for-medium { + display: none !important; } } + +@media screen and (max-width: 39.9375em) { + .show-for-medium { + display: none !important; } } + +@media screen and (min-width: 40em) and (max-width: 63.9375em) { + .hide-for-medium-only { + display: none !important; } } + +@media screen and (max-width: 39.9375em), screen and (min-width: 64em) { + .show-for-medium-only { + display: none !important; } } + +@media screen and (min-width: 64em) { + .hide-for-large { + display: none !important; } } + +@media screen and (max-width: 63.9375em) { + .show-for-large { + display: none !important; } } + +@media screen and (min-width: 64em) and (max-width: 74.9375em) { + .hide-for-large-only { + display: none !important; } } + +@media screen and (max-width: 63.9375em), screen and (min-width: 75em) { + .show-for-large-only { + display: none !important; } } + +.show-for-sr, +.show-on-focus { + position: absolute !important; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); } + +.show-on-focus:active, .show-on-focus:focus { + position: static !important; + height: auto; + width: auto; + overflow: visible; + clip: auto; } + +.show-for-landscape, +.hide-for-portrait { + display: block !important; } + @media screen and (orientation: landscape) { + .show-for-landscape, + .hide-for-portrait { + display: block !important; } } + @media screen and (orientation: portrait) { + .show-for-landscape, + .hide-for-portrait { + display: none !important; } } + +.hide-for-landscape, +.show-for-portrait { + display: none !important; } + @media screen and (orientation: landscape) { + .hide-for-landscape, + .show-for-portrait { + display: none !important; } } + @media screen and (orientation: portrait) { + .hide-for-landscape, + .show-for-portrait { + display: block !important; } } + +.float-left { + float: left !important; } + +.float-right { + float: right !important; } + +.float-center { + display: block; + margin-left: auto; + margin-right: auto; } + +.clearfix::before, .clearfix::after { + content: ' '; + display: table; } + +.clearfix::after { + clear: both; } + +/*# sourceMappingURL=foundation.css.map */ diff --git a/sopds_web_backend/static/css/foundation.min.css b/sopds_web_backend/static/css/foundation.min.css new file mode 100644 index 0000000000000000000000000000000000000000..32ce416be270833a95840f907577622cb4d0edbb --- /dev/null +++ b/sopds_web_backend/static/css/foundation.min.css @@ -0,0 +1,2 @@ +@charset "UTF-8"; +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:not-allowed}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{font-size:100%;box-sizing:border-box}*,:after,:before{box-sizing:inherit}body{padding:0;margin:0;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;color:#0a0a0a;background:#fefefe;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}img{max-width:100%;height:auto;-ms-interpolation-mode:bicubic;display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px;border-radius:0}select{width:100%;border-radius:0}#map_canvas embed,#map_canvas img,#map_canvas object,.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;background:transparent;padding:0;border:0;border-radius:0;line-height:1}[data-whatinput=mouse] button{outline:0}.is-visible{display:block!important}.is-hidden{display:none!important}.row{max-width:75rem;margin-left:auto;margin-right:auto}.row:after,.row:before{content:' ';display:table}.row:after{clear:both}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0}.row .row{margin-left:-.625rem;margin-right:-.625rem}@media screen and (min-width:40em){.row .row{margin-left:-.9375rem;margin-right:-.9375rem}}.row .row.collapse{margin-left:0;margin-right:0}.row.expanded{max-width:none}.row.expanded .row{margin-left:auto;margin-right:auto}.column,.columns{width:100%;float:left;padding-left:.625rem;padding-right:.625rem}@media screen and (min-width:40em){.column,.columns{padding-left:.9375rem;padding-right:.9375rem}}.column:last-child:not(:first-child),.columns:last-child:not(:first-child){float:right}.column.end:last-child:last-child,.end.columns:last-child:last-child{float:left}.column.row.row,.row.row.columns{float:none}.row .column.row.row,.row .row.row.columns{padding-left:0;padding-right:0;margin-left:0;margin-right:0}.small-1{width:8.33333%}.small-push-1{position:relative;left:8.33333%}.small-pull-1{position:relative;left:-8.33333%}.small-offset-0{margin-left:0}.small-2{width:16.66667%}.small-push-2{position:relative;left:16.66667%}.small-pull-2{position:relative;left:-16.66667%}.small-offset-1{margin-left:8.33333%}.small-3{width:25%}.small-push-3{position:relative;left:25%}.small-pull-3{position:relative;left:-25%}.small-offset-2{margin-left:16.66667%}.small-4{width:33.33333%}.small-push-4{position:relative;left:33.33333%}.small-pull-4{position:relative;left:-33.33333%}.small-offset-3{margin-left:25%}.small-5{width:41.66667%}.small-push-5{position:relative;left:41.66667%}.small-pull-5{position:relative;left:-41.66667%}.small-offset-4{margin-left:33.33333%}.small-6{width:50%}.small-push-6{position:relative;left:50%}.small-pull-6{position:relative;left:-50%}.small-offset-5{margin-left:41.66667%}.small-7{width:58.33333%}.small-push-7{position:relative;left:58.33333%}.small-pull-7{position:relative;left:-58.33333%}.small-offset-6{margin-left:50%}.small-8{width:66.66667%}.small-push-8{position:relative;left:66.66667%}.small-pull-8{position:relative;left:-66.66667%}.small-offset-7{margin-left:58.33333%}.small-9{width:75%}.small-push-9{position:relative;left:75%}.small-pull-9{position:relative;left:-75%}.small-offset-8{margin-left:66.66667%}.small-10{width:83.33333%}.small-push-10{position:relative;left:83.33333%}.small-pull-10{position:relative;left:-83.33333%}.small-offset-9{margin-left:75%}.small-11{width:91.66667%}.small-push-11{position:relative;left:91.66667%}.small-pull-11{position:relative;left:-91.66667%}.small-offset-10{margin-left:83.33333%}.small-12{width:100%}.small-offset-11{margin-left:91.66667%}.small-up-1>.column,.small-up-1>.columns{width:100%;float:left}.small-up-1>.column:nth-of-type(1n),.small-up-1>.columns:nth-of-type(1n){clear:none}.small-up-1>.column:nth-of-type(1n+1),.small-up-1>.columns:nth-of-type(1n+1){clear:both}.small-up-1>.column:last-child,.small-up-1>.columns:last-child{float:left}.small-up-2>.column,.small-up-2>.columns{width:50%;float:left}.small-up-2>.column:nth-of-type(1n),.small-up-2>.columns:nth-of-type(1n){clear:none}.small-up-2>.column:nth-of-type(2n+1),.small-up-2>.columns:nth-of-type(2n+1){clear:both}.small-up-2>.column:last-child,.small-up-2>.columns:last-child{float:left}.small-up-3>.column,.small-up-3>.columns{width:33.33333%;float:left}.small-up-3>.column:nth-of-type(1n),.small-up-3>.columns:nth-of-type(1n){clear:none}.small-up-3>.column:nth-of-type(3n+1),.small-up-3>.columns:nth-of-type(3n+1){clear:both}.small-up-3>.column:last-child,.small-up-3>.columns:last-child{float:left}.small-up-4>.column,.small-up-4>.columns{width:25%;float:left}.small-up-4>.column:nth-of-type(1n),.small-up-4>.columns:nth-of-type(1n){clear:none}.small-up-4>.column:nth-of-type(4n+1),.small-up-4>.columns:nth-of-type(4n+1){clear:both}.small-up-4>.column:last-child,.small-up-4>.columns:last-child{float:left}.small-up-5>.column,.small-up-5>.columns{width:20%;float:left}.small-up-5>.column:nth-of-type(1n),.small-up-5>.columns:nth-of-type(1n){clear:none}.small-up-5>.column:nth-of-type(5n+1),.small-up-5>.columns:nth-of-type(5n+1){clear:both}.small-up-5>.column:last-child,.small-up-5>.columns:last-child{float:left}.small-up-6>.column,.small-up-6>.columns{width:16.66667%;float:left}.small-up-6>.column:nth-of-type(1n),.small-up-6>.columns:nth-of-type(1n){clear:none}.small-up-6>.column:nth-of-type(6n+1),.small-up-6>.columns:nth-of-type(6n+1){clear:both}.small-up-6>.column:last-child,.small-up-6>.columns:last-child{float:left}.small-up-7>.column,.small-up-7>.columns{width:14.28571%;float:left}.small-up-7>.column:nth-of-type(1n),.small-up-7>.columns:nth-of-type(1n){clear:none}.small-up-7>.column:nth-of-type(7n+1),.small-up-7>.columns:nth-of-type(7n+1){clear:both}.small-up-7>.column:last-child,.small-up-7>.columns:last-child{float:left}.small-up-8>.column,.small-up-8>.columns{width:12.5%;float:left}.small-up-8>.column:nth-of-type(1n),.small-up-8>.columns:nth-of-type(1n){clear:none}.small-up-8>.column:nth-of-type(8n+1),.small-up-8>.columns:nth-of-type(8n+1){clear:both}.small-up-8>.column:last-child,.small-up-8>.columns:last-child{float:left}.small-collapse>.column,.small-collapse>.columns{padding-left:0;padding-right:0}.expanded.row .small-collapse.row,.small-collapse .row{margin-left:0;margin-right:0}.small-uncollapse>.column,.small-uncollapse>.columns{padding-left:.625rem;padding-right:.625rem}.small-centered{margin-left:auto;margin-right:auto}.small-centered,.small-centered:last-child:not(:first-child){float:none;clear:both}.small-pull-0,.small-push-0,.small-uncentered{position:static;margin-left:0;margin-right:0;float:left}@media screen and (min-width:40em){.medium-1{width:8.33333%}.medium-push-1{position:relative;left:8.33333%}.medium-pull-1{position:relative;left:-8.33333%}.medium-offset-0{margin-left:0}.medium-2{width:16.66667%}.medium-push-2{position:relative;left:16.66667%}.medium-pull-2{position:relative;left:-16.66667%}.medium-offset-1{margin-left:8.33333%}.medium-3{width:25%}.medium-push-3{position:relative;left:25%}.medium-pull-3{position:relative;left:-25%}.medium-offset-2{margin-left:16.66667%}.medium-4{width:33.33333%}.medium-push-4{position:relative;left:33.33333%}.medium-pull-4{position:relative;left:-33.33333%}.medium-offset-3{margin-left:25%}.medium-5{width:41.66667%}.medium-push-5{position:relative;left:41.66667%}.medium-pull-5{position:relative;left:-41.66667%}.medium-offset-4{margin-left:33.33333%}.medium-6{width:50%}.medium-push-6{position:relative;left:50%}.medium-pull-6{position:relative;left:-50%}.medium-offset-5{margin-left:41.66667%}.medium-7{width:58.33333%}.medium-push-7{position:relative;left:58.33333%}.medium-pull-7{position:relative;left:-58.33333%}.medium-offset-6{margin-left:50%}.medium-8{width:66.66667%}.medium-push-8{position:relative;left:66.66667%}.medium-pull-8{position:relative;left:-66.66667%}.medium-offset-7{margin-left:58.33333%}.medium-9{width:75%}.medium-push-9{position:relative;left:75%}.medium-pull-9{position:relative;left:-75%}.medium-offset-8{margin-left:66.66667%}.medium-10{width:83.33333%}.medium-push-10{position:relative;left:83.33333%}.medium-pull-10{position:relative;left:-83.33333%}.medium-offset-9{margin-left:75%}.medium-11{width:91.66667%}.medium-push-11{position:relative;left:91.66667%}.medium-pull-11{position:relative;left:-91.66667%}.medium-offset-10{margin-left:83.33333%}.medium-12{width:100%}.medium-offset-11{margin-left:91.66667%}.medium-up-1>.column,.medium-up-1>.columns{width:100%;float:left}.medium-up-1>.column:nth-of-type(1n),.medium-up-1>.columns:nth-of-type(1n){clear:none}.medium-up-1>.column:nth-of-type(1n+1),.medium-up-1>.columns:nth-of-type(1n+1){clear:both}.medium-up-1>.column:last-child,.medium-up-1>.columns:last-child{float:left}.medium-up-2>.column,.medium-up-2>.columns{width:50%;float:left}.medium-up-2>.column:nth-of-type(1n),.medium-up-2>.columns:nth-of-type(1n){clear:none}.medium-up-2>.column:nth-of-type(2n+1),.medium-up-2>.columns:nth-of-type(2n+1){clear:both}.medium-up-2>.column:last-child,.medium-up-2>.columns:last-child{float:left}.medium-up-3>.column,.medium-up-3>.columns{width:33.33333%;float:left}.medium-up-3>.column:nth-of-type(1n),.medium-up-3>.columns:nth-of-type(1n){clear:none}.medium-up-3>.column:nth-of-type(3n+1),.medium-up-3>.columns:nth-of-type(3n+1){clear:both}.medium-up-3>.column:last-child,.medium-up-3>.columns:last-child{float:left}.medium-up-4>.column,.medium-up-4>.columns{width:25%;float:left}.medium-up-4>.column:nth-of-type(1n),.medium-up-4>.columns:nth-of-type(1n){clear:none}.medium-up-4>.column:nth-of-type(4n+1),.medium-up-4>.columns:nth-of-type(4n+1){clear:both}.medium-up-4>.column:last-child,.medium-up-4>.columns:last-child{float:left}.medium-up-5>.column,.medium-up-5>.columns{width:20%;float:left}.medium-up-5>.column:nth-of-type(1n),.medium-up-5>.columns:nth-of-type(1n){clear:none}.medium-up-5>.column:nth-of-type(5n+1),.medium-up-5>.columns:nth-of-type(5n+1){clear:both}.medium-up-5>.column:last-child,.medium-up-5>.columns:last-child{float:left}.medium-up-6>.column,.medium-up-6>.columns{width:16.66667%;float:left}.medium-up-6>.column:nth-of-type(1n),.medium-up-6>.columns:nth-of-type(1n){clear:none}.medium-up-6>.column:nth-of-type(6n+1),.medium-up-6>.columns:nth-of-type(6n+1){clear:both}.medium-up-6>.column:last-child,.medium-up-6>.columns:last-child{float:left}.medium-up-7>.column,.medium-up-7>.columns{width:14.28571%;float:left}.medium-up-7>.column:nth-of-type(1n),.medium-up-7>.columns:nth-of-type(1n){clear:none}.medium-up-7>.column:nth-of-type(7n+1),.medium-up-7>.columns:nth-of-type(7n+1){clear:both}.medium-up-7>.column:last-child,.medium-up-7>.columns:last-child{float:left}.medium-up-8>.column,.medium-up-8>.columns{width:12.5%;float:left}.medium-up-8>.column:nth-of-type(1n),.medium-up-8>.columns:nth-of-type(1n){clear:none}.medium-up-8>.column:nth-of-type(8n+1),.medium-up-8>.columns:nth-of-type(8n+1){clear:both}.medium-up-8>.column:last-child,.medium-up-8>.columns:last-child{float:left}.medium-collapse>.column,.medium-collapse>.columns{padding-left:0;padding-right:0}.expanded.row .medium-collapse.row,.medium-collapse .row{margin-left:0;margin-right:0}.medium-uncollapse>.column,.medium-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.medium-centered{margin-left:auto;margin-right:auto}.medium-centered,.medium-centered:last-child:not(:first-child){float:none;clear:both}.medium-pull-0,.medium-push-0,.medium-uncentered{position:static;margin-left:0;margin-right:0;float:left}}@media screen and (min-width:64em){.large-1{width:8.33333%}.large-push-1{position:relative;left:8.33333%}.large-pull-1{position:relative;left:-8.33333%}.large-offset-0{margin-left:0}.large-2{width:16.66667%}.large-push-2{position:relative;left:16.66667%}.large-pull-2{position:relative;left:-16.66667%}.large-offset-1{margin-left:8.33333%}.large-3{width:25%}.large-push-3{position:relative;left:25%}.large-pull-3{position:relative;left:-25%}.large-offset-2{margin-left:16.66667%}.large-4{width:33.33333%}.large-push-4{position:relative;left:33.33333%}.large-pull-4{position:relative;left:-33.33333%}.large-offset-3{margin-left:25%}.large-5{width:41.66667%}.large-push-5{position:relative;left:41.66667%}.large-pull-5{position:relative;left:-41.66667%}.large-offset-4{margin-left:33.33333%}.large-6{width:50%}.large-push-6{position:relative;left:50%}.large-pull-6{position:relative;left:-50%}.large-offset-5{margin-left:41.66667%}.large-7{width:58.33333%}.large-push-7{position:relative;left:58.33333%}.large-pull-7{position:relative;left:-58.33333%}.large-offset-6{margin-left:50%}.large-8{width:66.66667%}.large-push-8{position:relative;left:66.66667%}.large-pull-8{position:relative;left:-66.66667%}.large-offset-7{margin-left:58.33333%}.large-9{width:75%}.large-push-9{position:relative;left:75%}.large-pull-9{position:relative;left:-75%}.large-offset-8{margin-left:66.66667%}.large-10{width:83.33333%}.large-push-10{position:relative;left:83.33333%}.large-pull-10{position:relative;left:-83.33333%}.large-offset-9{margin-left:75%}.large-11{width:91.66667%}.large-push-11{position:relative;left:91.66667%}.large-pull-11{position:relative;left:-91.66667%}.large-offset-10{margin-left:83.33333%}.large-12{width:100%}.large-offset-11{margin-left:91.66667%}.large-up-1>.column,.large-up-1>.columns{width:100%;float:left}.large-up-1>.column:nth-of-type(1n),.large-up-1>.columns:nth-of-type(1n){clear:none}.large-up-1>.column:nth-of-type(1n+1),.large-up-1>.columns:nth-of-type(1n+1){clear:both}.large-up-1>.column:last-child,.large-up-1>.columns:last-child{float:left}.large-up-2>.column,.large-up-2>.columns{width:50%;float:left}.large-up-2>.column:nth-of-type(1n),.large-up-2>.columns:nth-of-type(1n){clear:none}.large-up-2>.column:nth-of-type(2n+1),.large-up-2>.columns:nth-of-type(2n+1){clear:both}.large-up-2>.column:last-child,.large-up-2>.columns:last-child{float:left}.large-up-3>.column,.large-up-3>.columns{width:33.33333%;float:left}.large-up-3>.column:nth-of-type(1n),.large-up-3>.columns:nth-of-type(1n){clear:none}.large-up-3>.column:nth-of-type(3n+1),.large-up-3>.columns:nth-of-type(3n+1){clear:both}.large-up-3>.column:last-child,.large-up-3>.columns:last-child{float:left}.large-up-4>.column,.large-up-4>.columns{width:25%;float:left}.large-up-4>.column:nth-of-type(1n),.large-up-4>.columns:nth-of-type(1n){clear:none}.large-up-4>.column:nth-of-type(4n+1),.large-up-4>.columns:nth-of-type(4n+1){clear:both}.large-up-4>.column:last-child,.large-up-4>.columns:last-child{float:left}.large-up-5>.column,.large-up-5>.columns{width:20%;float:left}.large-up-5>.column:nth-of-type(1n),.large-up-5>.columns:nth-of-type(1n){clear:none}.large-up-5>.column:nth-of-type(5n+1),.large-up-5>.columns:nth-of-type(5n+1){clear:both}.large-up-5>.column:last-child,.large-up-5>.columns:last-child{float:left}.large-up-6>.column,.large-up-6>.columns{width:16.66667%;float:left}.large-up-6>.column:nth-of-type(1n),.large-up-6>.columns:nth-of-type(1n){clear:none}.large-up-6>.column:nth-of-type(6n+1),.large-up-6>.columns:nth-of-type(6n+1){clear:both}.large-up-6>.column:last-child,.large-up-6>.columns:last-child{float:left}.large-up-7>.column,.large-up-7>.columns{width:14.28571%;float:left}.large-up-7>.column:nth-of-type(1n),.large-up-7>.columns:nth-of-type(1n){clear:none}.large-up-7>.column:nth-of-type(7n+1),.large-up-7>.columns:nth-of-type(7n+1){clear:both}.large-up-7>.column:last-child,.large-up-7>.columns:last-child{float:left}.large-up-8>.column,.large-up-8>.columns{width:12.5%;float:left}.large-up-8>.column:nth-of-type(1n),.large-up-8>.columns:nth-of-type(1n){clear:none}.large-up-8>.column:nth-of-type(8n+1),.large-up-8>.columns:nth-of-type(8n+1){clear:both}.large-up-8>.column:last-child,.large-up-8>.columns:last-child{float:left}.large-collapse>.column,.large-collapse>.columns{padding-left:0;padding-right:0}.expanded.row .large-collapse.row,.large-collapse .row{margin-left:0;margin-right:0}.large-uncollapse>.column,.large-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.large-centered{margin-left:auto;margin-right:auto}.large-centered,.large-centered:last-child:not(:first-child){float:none;clear:both}.large-pull-0,.large-push-0,.large-uncentered{position:static;margin-left:0;margin-right:0;float:left}}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{font-size:inherit;line-height:1.6;margin-bottom:1rem;text-rendering:optimizeLegibility}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}h1,h2,h3,h4,h5,h6{font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;font-style:normal;color:inherit;text-rendering:optimizeLegibility;margin-top:0;margin-bottom:.5rem;line-height:1.4}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.1875rem}h4{font-size:1.125rem}h5{font-size:1.0625rem}h6{font-size:1rem}@media screen and (min-width:40em){h1{font-size:3rem}h2{font-size:2.5rem}h3{font-size:1.9375rem}h4{font-size:1.5625rem}h5{font-size:1.25rem}h6{font-size:1rem}}a{color:#2199e8;text-decoration:none;line-height:inherit;cursor:pointer}a:focus,a:hover{color:#1585cf}a img{border:0}hr{max-width:75rem;height:0;border-right:0;border-top:0;border-bottom:1px solid #cacaca;border-left:0;margin:1.25rem auto;clear:both}dl,ol,ul{line-height:1.6;margin-bottom:1rem;list-style-position:outside}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-left:1.25rem;margin-bottom:0}dl{margin-bottom:1rem}dl dt{margin-bottom:.3rem;font-weight:700}blockquote{margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem;border-left:1px solid #cacaca}blockquote,blockquote p{line-height:1.6;color:#8a8a8a}cite{display:block;font-size:.8125rem;color:#8a8a8a}cite:before{content:'\2014 \0020'}abbr{color:#0a0a0a;cursor:help;border-bottom:1px dotted #0a0a0a}code{font-weight:400;border:1px solid #cacaca;padding:.125rem .3125rem .0625rem}code,kbd{font-family:Consolas,Liberation Mono,Courier,monospace;color:#0a0a0a;background-color:#e6e6e6}kbd{padding:.125rem .25rem 0;margin:0}.subheader{margin-top:.2rem;margin-bottom:.5rem;font-weight:400;line-height:1.4;color:#8a8a8a}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}.no-bullet{margin-left:0;list-style:none}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^='#']:after,a[href^='javascript:']:after{content:''}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{display:block;box-sizing:border-box;width:100%;height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-family:inherit;font-size:1rem;color:#0a0a0a;background-color:#fefefe;box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);border-radius:0;-webkit-transition:-webkit-box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out;-webkit-appearance:none;-moz-appearance:none}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{border:1px solid #8a8a8a;background-color:#fefefe;outline:none;box-shadow:0 0 5px #cacaca;-webkit-transition:-webkit-box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out}textarea{max-width:100%}textarea[rows]{height:auto}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#cacaca}input::-moz-placeholder,textarea::-moz-placeholder{color:#cacaca}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#cacaca}input::placeholder,textarea::placeholder{color:#cacaca}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{border-radius:0;-webkit-appearance:none;-moz-appearance:none}input[type=search]{box-sizing:border-box}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-left:.5rem;margin-right:1rem;margin-bottom:0;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{display:block;margin:0;font-size:.875rem;font-weight:400;line-height:1.8;color:#0a0a0a}label.middle{margin:0 0 1rem;padding:.5625rem 0}.help-text{margin-top:-.5rem;font-size:.8125rem;font-style:italic;color:#0a0a0a}.input-group{display:table;width:100%;margin-bottom:1rem}.input-group>:first-child,.input-group>:last-child>*{border-radius:0 0 0 0}.input-group-button,.input-group-field,.input-group-label{margin:0;white-space:nowrap;display:table-cell;vertical-align:middle}.input-group-label{text-align:center;padding:0 1rem;background:#e6e6e6;color:#0a0a0a;border:1px solid #cacaca;white-space:nowrap;width:1%;height:100%}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{border-radius:0;height:2.5rem}.input-group-button{padding-top:0;padding-bottom:0;text-align:center;height:100%;width:1%}.input-group-button a,.input-group-button button,.input-group-button input{margin:0}.input-group .input-group-button{display:table-cell}fieldset{border:0;padding:0;margin:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;padding:1.25rem;margin:1.125rem 0}.fieldset legend{background:#fefefe;padding:0 .1875rem;margin:0;margin-left:-.1875rem}select{height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-size:1rem;font-family:inherit;line-height:normal;color:#0a0a0a;background-color:#fefefe;border-radius:0;-webkit-appearance:none;-moz-appearance:none;background-image:url("data:image/svg+xml;utf8,");background-size:9px 6px;background-position:right -1rem center;background-origin:content-box;background-repeat:no-repeat;padding-right:1.5rem}@media screen and (min-width:0\0){select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==")}}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{height:auto;background-image:none}.is-invalid-input:not(:focus){background-color:rgba(236,88,64,.1);border-color:#ec5840}.form-error,.is-invalid-label{color:#ec5840}.form-error{display:none;margin-top:-.5rem;margin-bottom:1rem;font-size:.75rem;font-weight:700}.form-error.is-visible{display:block}.button{display:inline-block;text-align:center;line-height:1;cursor:pointer;-webkit-appearance:none;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle;border:1px solid transparent;border-radius:0;padding:.85em 1em;margin:0 0 1rem;font-size:.9rem;background-color:#2199e8;color:#fefefe}[data-whatinput=mouse] .button{outline:0}.button:focus,.button:hover{background-color:#1583cc;color:#fefefe}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;width:100%;margin-left:0;margin-right:0}.button.primary{background-color:#2199e8;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#147cc0;color:#fefefe}.button.secondary{background-color:#777;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5f5f5f;color:#fefefe}.button.success{background-color:#3adb76;color:#fefefe}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#fefefe}.button.warning{background-color:#ffae00;color:#fefefe}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#fefefe}.button.alert{background-color:#ec5840;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#da3116;color:#fefefe}.button.hollow{border:1px solid #2199e8;color:#2199e8}.button.hollow,.button.hollow:focus,.button.hollow:hover{background-color:transparent}.button.hollow:focus,.button.hollow:hover{border-color:#0c4d78;color:#0c4d78}.button.hollow.primary{border:1px solid #2199e8;color:#2199e8}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c4d78;color:#0c4d78}.button.hollow.secondary{border:1px solid #777;color:#777}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3c3c3c;color:#3c3c3c}.button.hollow.success{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert{border:1px solid #ec5840;color:#ec5840}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#881f0e;color:#881f0e}.button.disabled,.button[disabled]{opacity:.25;cursor:not-allowed}.button.disabled:focus,.button.disabled:hover,.button[disabled]:focus,.button[disabled]:hover{background-color:#2199e8;color:#fefefe}.button.disabled.primary,.button[disabled].primary{opacity:.25;cursor:not-allowed}.button.disabled.primary:focus,.button.disabled.primary:hover,.button[disabled].primary:focus,.button[disabled].primary:hover{background-color:#2199e8;color:#fefefe}.button.disabled.secondary,.button[disabled].secondary{opacity:.25;cursor:not-allowed}.button.disabled.secondary:focus,.button.disabled.secondary:hover,.button[disabled].secondary:focus,.button[disabled].secondary:hover{background-color:#777;color:#fefefe}.button.disabled.success,.button[disabled].success{opacity:.25;cursor:not-allowed}.button.disabled.success:focus,.button.disabled.success:hover,.button[disabled].success:focus,.button[disabled].success:hover{background-color:#3adb76;color:#fefefe}.button.disabled.warning,.button[disabled].warning{opacity:.25;cursor:not-allowed}.button.disabled.warning:focus,.button.disabled.warning:hover,.button[disabled].warning:focus,.button[disabled].warning:hover{background-color:#ffae00;color:#fefefe}.button.disabled.alert,.button[disabled].alert{opacity:.25;cursor:not-allowed}.button.disabled.alert:focus,.button.disabled.alert:hover,.button[disabled].alert:focus,.button[disabled].alert:hover{background-color:#ec5840;color:#fefefe}.button.dropdown:after{content:'';display:block;width:0;height:0;border:.4em inset;border-color:#fefefe transparent transparent;border-top-style:solid;border-bottom-width:0;position:relative;top:.4em;float:right;margin-left:1em;display:inline-block}.button.arrow-only:after{margin-left:0;float:none;top:-.1em}.accordion{list-style-type:none;background:#fefefe;margin-left:0}.accordion-item:first-child>:first-child,.accordion-item:last-child>:last-child{border-radius:0 0 0 0}.accordion-title{display:block;padding:1.25rem 1rem;line-height:1;font-size:.75rem;color:#2199e8;position:relative;border:1px solid #e6e6e6;border-bottom:0}:last-child:not(.is-active)>.accordion-title{border-radius:0 0 0 0;border-bottom:1px solid #e6e6e6}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:'+';position:absolute;right:1rem;top:50%;margin-top:-.5rem}.is-active>.accordion-title:before{content:'–'}.accordion-content{padding:1rem;display:none;border:1px solid #e6e6e6;border-bottom:0;background-color:#fefefe;color:#0a0a0a}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.is-accordion-submenu-parent>a{position:relative}.is-accordion-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:6px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;position:absolute;top:50%;margin-top:-4px;right:1rem}.is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform-origin:50% 50%;transform-origin:50% 50%;-webkit-transform:scaleY(-1);transform:scaleY(-1)}.badge{display:inline-block;padding:.3em;min-width:2.1em;font-size:.6rem;text-align:center;border-radius:50%;background:#2199e8;color:#fefefe}.badge.secondary{background:#777;color:#fefefe}.badge.success{background:#3adb76;color:#fefefe}.badge.warning{background:#ffae00;color:#fefefe}.badge.alert{background:#ec5840;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{content:' ';display:table}.breadcrumbs:after{clear:both}.breadcrumbs li{float:left;color:#0a0a0a;font-size:.6875rem;cursor:default;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;position:relative;top:1px;opacity:1}.breadcrumbs a{color:#2199e8}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.button-group{margin-bottom:1rem;font-size:0}.button-group:after,.button-group:before{content:' ';display:table}.button-group:after{clear:both}.button-group .button{margin:0;margin-right:1px;margin-bottom:1px;font-size:.9rem}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded{margin-right:-1px}.button-group.expanded:after,.button-group.expanded:before{display:none}.button-group.expanded .button:first-child:nth-last-child(2),.button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2)~.button{display:inline-block;width:calc(50% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(2):last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(3),.button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3)~.button{display:inline-block;width:calc(33.33333% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(3):last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(4),.button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4)~.button{display:inline-block;width:calc(25% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(4):last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(5),.button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5)~.button{display:inline-block;width:calc(20% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(5):last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(6),.button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6)~.button{display:inline-block;width:calc(16.66667% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6)~.button:last-child,.button-group.expanded .button:first-child:nth-last-child(6):last-child{margin-right:-6px}.button-group.primary .button{background-color:#2199e8;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#147cc0;color:#fefefe}.button-group.secondary .button{background-color:#777;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5f5f5f;color:#fefefe}.button-group.success .button{background-color:#3adb76;color:#fefefe}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#fefefe}.button-group.warning .button{background-color:#ffae00;color:#fefefe}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#fefefe}.button-group.alert .button{background-color:#ec5840;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#da3116;color:#fefefe}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{width:100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}@media screen and (min-width:40em){.button-group.stacked-for-small .button{width:auto;margin-bottom:0}}@media screen and (min-width:64em){.button-group.stacked-for-medium .button{width:auto;margin-bottom:0}}@media screen and (max-width:39.9375em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}.callout{margin:0 0 1rem;padding:1rem;border:1px solid hsla(0,0%,4%,.25);border-radius:0;position:relative;color:#0a0a0a;background-color:#fff}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#def0fc}.callout.secondary{background-color:#ebebeb}.callout.success{background-color:#e1faea}.callout.warning{background-color:#fff3d9}.callout.alert{background-color:#fce6e2}.callout.small{padding:.5rem}.callout.large{padding:3rem}.close-button{position:absolute;color:#8a8a8a;right:1rem;top:.5rem;font-size:2em;line-height:1;cursor:pointer}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.menu{margin:0;list-style-type:none}.menu>li{display:table-cell;vertical-align:middle}[data-whatinput=mouse] .menu>li{outline:0}.menu>li>a{display:block;padding:.7rem 1rem;line-height:1}.menu a,.menu button,.menu input{margin-bottom:0}.menu>li>a i,.menu>li>a i+span,.menu>li>a img,.menu>li>a img+span,.menu>li>a svg,.menu>li>a svg+span{vertical-align:middle}.menu>li>a i,.menu>li>a img,.menu>li>a svg{margin-right:.25rem;display:inline-block}.menu>li{display:table-cell}.menu.vertical>li{display:block}@media screen and (min-width:40em){.menu.medium-horizontal>li{display:table-cell}.menu.medium-vertical>li{display:block}}@media screen and (min-width:64em){.menu.large-horizontal>li{display:table-cell}.menu.large-vertical>li{display:block}}.menu.simple li{line-height:1;display:inline-block;margin-right:1rem}.menu.simple a{padding:0}.menu.align-right:after,.menu.align-right:before{content:' ';display:table}.menu.align-right:after{clear:both}.menu.align-right>li{float:right}.menu.expanded{width:100%;display:table;table-layout:fixed}.menu.expanded>li:first-child:last-child{width:100%}.menu.icon-top>li>a{text-align:center}.menu.icon-top>li>a i,.menu.icon-top>li>a img,.menu.icon-top>li>a svg{display:block;margin:0 auto .25rem}.menu.nested{margin-left:1rem}.menu .active>a{color:#fefefe;background:#2199e8}.menu-text{font-weight:700;color:inherit;line-height:1;padding-top:0;padding-bottom:0;padding:.7rem 1rem}.menu-centered{text-align:center}.menu-centered>.menu{display:inline-block}.no-js [data-responsive-menu] ul{display:none}.menu-icon{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon:after{content:'';position:absolute;display:block;width:100%;height:2px;background:#fefefe;top:0;left:0;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe}.menu-icon:hover:after{background:#cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon.dark:after{content:'';position:absolute;display:block;width:100%;height:2px;background:#0a0a0a;top:0;left:0;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a}.menu-icon.dark:hover:after{background:#8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.is-drilldown{position:relative;overflow:hidden}.is-drilldown li{display:block!important}.is-drilldown-submenu{position:absolute;top:0;left:100%;z-index:-1;width:100%;background:#fefefe;-webkit-transition:-webkit-transform .15s linear;transition:transform .15s linear}.is-drilldown-submenu.is-active{z-index:1;display:block;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);transform:translateX(100%)}.is-drilldown-submenu-parent>a{position:relative}.is-drilldown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:6px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0;position:absolute;top:50%;margin-top:-6px;right:1rem}.js-drilldown-back>a:before{content:'';display:block;width:0;height:0;border:6px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0;display:inline-block;vertical-align:middle;margin-right:.75rem}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:block;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-open{visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;right:5px;margin-top:-2px}[data-whatinput=mouse] .dropdown.menu a{outline:0}.no-js .dropdown.menu ul{display:none}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.vertical>li>a:after{right:14px;margin-top:-3px}.dropdown.menu.vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}@media screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;right:5px;margin-top:-2px}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.medium-vertical>li>a:after{right:14px;margin-top:-3px}.dropdown.menu.medium-vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}}@media screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:#2199e8 transparent transparent;border-top-style:solid;border-bottom-width:0;right:5px;margin-top:-2px}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}.dropdown.menu.large-vertical>li>a:after{right:14px;margin-top:-3px}.dropdown.menu.large-vertical>li.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{top:100%;left:auto;right:0}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{position:absolute;top:50%;right:5px;margin-top:-2px}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{top:100%;left:auto}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{right:auto;left:100%}.is-dropdown-submenu{display:none;position:absolute;top:0;left:100%;min-width:200px;z-index:1;background:#fefefe;border:1px solid #cacaca}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px;margin-top:-3px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent #2199e8 transparent transparent;border-right-style:solid;border-left-width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{content:'';display:block;width:0;height:0;border:5px inset;border-color:transparent transparent transparent #2199e8;border-left-style:solid;border-right-width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.flex-video{position:relative;height:0;padding-bottom:75%;margin-bottom:1rem;overflow:hidden}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video{position:absolute;top:0;left:0;width:100%;height:100%}.flex-video.widescreen{padding-bottom:56.25%}.flex-video.vimeo{padding-top:0}.label{display:inline-block;padding:.33333rem .5rem;font-size:.8rem;line-height:1;white-space:nowrap;cursor:default;border-radius:0;background:#2199e8;color:#fefefe}.label.secondary{background:#777;color:#fefefe}.label.success{background:#3adb76;color:#fefefe}.label.warning{background:#ffae00;color:#fefefe}.label.alert{background:#ec5840;color:#fefefe}.media-object{margin-bottom:1rem;display:block}.media-object img{max-width:none}@media screen and (max-width:39.9375em){.media-object.stack-for-small .media-object-section{padding:0;padding-bottom:1rem;display:block}.media-object.stack-for-small .media-object-section img{width:100%}}.media-object-section{display:table-cell;vertical-align:top}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}.media-object-section.middle{vertical-align:middle}.media-object-section.bottom{vertical-align:bottom}body,html{height:100%}.off-canvas-wrapper{width:100%;overflow-x:hidden;position:relative;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-overflow-scrolling:auto}.off-canvas-wrapper-inner{position:relative;width:100%;min-height:100%;-webkit-transition:-webkit-transform .5s ease;transition:transform .5s ease}.off-canvas-wrapper-inner:after,.off-canvas-wrapper-inner:before{content:' ';display:table}.off-canvas-wrapper-inner:after{clear:both}.off-canvas-content{min-height:100%;background:#fefefe;-webkit-transition:-webkit-transform .5s ease;transition:transform .5s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1;padding-bottom:.1px;box-shadow:0 0 10px hsla(0,0%,4%,.5)}.js-off-canvas-exit{display:none;position:absolute;top:0;left:0;width:100%;height:100%;background:hsla(0,0%,100%,.25);cursor:pointer;-webkit-transition:background .5s ease;transition:background .5s ease}.off-canvas{position:absolute;background:#e6e6e6;z-index:-1;max-height:100%;overflow-y:auto;-webkit-transform:translateX(0);transform:translateX(0)}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.position-left{left:-250px;top:0;width:250px}.is-open-left{-webkit-transform:translateX(250px);transform:translateX(250px)}.off-canvas.position-right{right:-250px;top:0;width:250px}.is-open-right{-webkit-transform:translateX(-250px);transform:translateX(-250px)}@media screen and (min-width:40em){.position-left.reveal-for-medium{left:0;z-index:auto;position:fixed}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{right:0;z-index:auto;position:fixed}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}}@media screen and (min-width:64em){.position-left.reveal-for-large{left:0;z-index:auto;position:fixed}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{right:0;z-index:auto;position:fixed}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}}.orbit,.orbit-container{position:relative}.orbit-container{margin:0;overflow:hidden;list-style:none}.orbit-slide{width:100%;max-height:100%}.orbit-slide.no-motionui.is-active{top:0;left:0}.orbit-figure{margin:0}.orbit-image{margin:0;width:100%;max-width:100%}.orbit-caption{bottom:0;width:100%;margin-bottom:0;background-color:hsla(0,0%,4%,.5)}.orbit-caption,.orbit-next,.orbit-previous{position:absolute;padding:1rem;color:#fefefe}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{position:relative;margin-top:.8rem;margin-bottom:.8rem;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{width:1.2rem;height:1.2rem;margin:.1rem;background-color:#cacaca;border-radius:50%}.orbit-bullets button.is-active,.orbit-bullets button:hover{background-color:#8a8a8a}.pagination{margin-left:0;margin-bottom:1rem}.pagination:after,.pagination:before{content:' ';display:table}.pagination:after{clear:both}.pagination li{font-size:.875rem;margin-right:.0625rem;border-radius:0;display:none}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{color:#0a0a0a;display:block;padding:.1875rem .625rem;border-radius:0}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{padding:.1875rem .625rem;background:#2199e8;color:#fefefe;cursor:default}.pagination .disabled{padding:.1875rem .625rem;color:#cacaca;cursor:not-allowed}.pagination .disabled:hover{background:transparent}.pagination .ellipsis:after{content:'\2026';padding:.1875rem .625rem;color:#0a0a0a}.pagination-previous.disabled:before,.pagination-previous a:before{content:'\00ab';display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:'\00bb';display:inline-block;margin-left:.5rem}.progress{background-color:#cacaca;height:1rem;margin-bottom:1rem;border-radius:0}.progress.primary .progress-meter{background-color:#2199e8}.progress.secondary .progress-meter{background-color:#777}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#ec5840}.progress-meter{position:relative;display:block;width:0;height:100%;background-color:#2199e8}.progress-meter-text{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;margin:0;font-size:.75rem;font-weight:700;color:#fefefe;white-space:nowrap}.slider{position:relative;height:.5rem;margin-top:1.25rem;margin-bottom:2.25rem;background-color:#e6e6e6;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-touch-action:none;touch-action:none}.slider-fill{position:absolute;top:0;left:0;display:inline-block;max-width:100%;height:.5rem;background-color:#cacaca;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;left:0;z-index:1;display:inline-block;width:1.4rem;height:1.4rem;background-color:#2199e8;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-ms-touch-action:manipulation;touch-action:manipulation;border-radius:0}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#1583cc}.slider-handle.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{opacity:.25;cursor:not-allowed}.slider.vertical{display:inline-block;width:.5rem;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);transform:scaleY(-1)}.slider.vertical .slider-fill{top:0;width:.5rem;max-height:100%}.slider.vertical .slider-handle{position:absolute;top:0;left:50%;width:1.4rem;height:1.4rem;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.sticky-container{position:relative}.sticky{position:absolute;z-index:0;-webkit-transform:translateZ(0);transform:translateZ(0)}.sticky.is-stuck{position:fixed;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{position:absolute;left:auto;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}body.is-reveal-open{overflow:hidden}html.is-reveal-open,html.is-reveal-open body{min-height:100%;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.reveal-overlay{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:1005;background-color:hsla(0,0%,4%,.45);overflow-y:scroll}.reveal{display:none;z-index:1006;padding:1rem;border:1px solid #cacaca;background-color:#fefefe;border-radius:0;position:relative;top:100px;margin-left:auto;margin-right:auto;overflow-y:auto}[data-whatinput=mouse] .reveal{outline:0}@media screen and (min-width:40em){.reveal{min-height:0}}.reveal .column,.reveal .columns{min-width:0}.reveal>:last-child{margin-bottom:0}@media screen and (min-width:40em){.reveal{width:600px;max-width:75rem}}@media screen and (min-width:40em){.reveal .reveal{left:auto;right:auto;margin:0 auto}}.reveal.collapse{padding:0}@media screen and (min-width:40em){.reveal.tiny{width:30%;max-width:75rem}}@media screen and (min-width:40em){.reveal.small{width:50%;max-width:75rem}}@media screen and (min-width:40em){.reveal.large{width:90%;max-width:75rem}}.reveal.full{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}@media screen and (max-width:39.9375em){.reveal{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}}.reveal.without-overlay{position:fixed}.switch{height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fefefe;font-weight:700;font-size:.875rem}.switch-input{opacity:0;position:absolute;margin-bottom:0}.switch-paddle{background:#cacaca;cursor:pointer;display:block;position:relative;width:4rem;height:2rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;border-radius:0;color:inherit;font-weight:inherit}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;content:'';display:block;position:absolute;height:1.5rem;left:.25rem;top:.25rem;width:1.5rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;-webkit-transform:translateZ(0);transform:translateZ(0);border-radius:0}input:checked~.switch-paddle{background:#2199e8}input:checked~.switch-paddle:after{left:2.25rem}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{left:8%;display:none}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{width:3rem;height:1.5rem;font-size:.625rem}.switch.tiny .switch-paddle:after{width:1rem;height:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{width:3.5rem;height:1.75rem;font-size:.75rem}.switch.small .switch-paddle:after{width:1.25rem;height:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{width:5rem;height:2.5rem;font-size:1rem}.switch.large .switch-paddle:after{width:2rem;height:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{width:100%;margin-bottom:1rem;border-radius:0}table tbody,table tfoot,table thead{border:1px solid #f1f1f1;background-color:#fefefe}table caption{font-weight:700;padding:.5rem .625rem .625rem}table thead{background:#f8f8f8;color:#0a0a0a}table tfoot{background:#f1f1f1;color:#0a0a0a}table tfoot tr,table thead tr{background:transparent}table tfoot td,table tfoot th,table thead td,table thead th{padding:.5rem .625rem .625rem;font-weight:700;text-align:left}table tbody tr:nth-child(even){background-color:#f1f1f1}table tbody td,table tbody th{padding:.5rem .625rem .625rem}@media screen and (max-width:63.9375em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;width:100%;overflow-x:auto}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover tbody tr:nth-of-type(even):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.table-scroll table{width:auto}.tabs{margin:0;list-style-type:none;background:#fefefe;border:1px solid #e6e6e6}.tabs:after,.tabs:before{content:' ';display:table}.tabs:after{clear:both}.tabs.vertical>li{width:auto;float:none;display:block}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:transparent}.tabs.primary{background:#2199e8}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1893e4}.tabs-title{float:left}.tabs-title>a{display:block;padding:1.25rem 1.5rem;line-height:1;font-size:.75rem}.tabs-title>a:hover{background:#fefefe}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6}.tabs-content{background:#fefefe;-webkit-transition:all .5s ease;transition:all .5s ease;border:1px solid #e6e6e6;border-top:0}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;max-width:100%;-webkit-transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;border-radius:0;margin-bottom:1rem}.thumbnail:focus,.thumbnail:hover{box-shadow:0 0 6px 1px rgba(33,153,232,.5)}.title-bar{background:#0a0a0a;color:#fefefe;padding:.5rem}.title-bar:after,.title-bar:before{content:' ';display:table}.title-bar:after{clear:both}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left{float:left}.title-bar-right{float:right;text-align:right}.title-bar-title{vertical-align:middle}.has-tip,.title-bar-title{font-weight:700;display:inline-block}.has-tip{border-bottom:1px dotted #8a8a8a;position:relative;cursor:help}.tooltip{background-color:#0a0a0a;color:#fefefe;font-size:80%;padding:.75rem;position:absolute;z-index:10;top:calc(100% + .6495rem);max-width:10rem!important;border-radius:0}.tooltip:before{border:.75rem inset;border-color:transparent transparent #0a0a0a;border-bottom-style:solid;border-top-width:0;bottom:100%;position:absolute;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before,.tooltip:before{content:'';display:block;width:0;height:0}.tooltip.top:before{border:.75rem inset;border-color:#0a0a0a transparent transparent;border-top-style:solid;border-bottom-width:0;top:100%;bottom:auto}.tooltip.left:before{border:.75rem inset;border-color:transparent transparent transparent #0a0a0a;border-left-style:solid;border-right-width:0;left:100%}.tooltip.left:before,.tooltip.right:before{content:'';display:block;width:0;height:0;bottom:auto;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border:.75rem inset;border-color:transparent #0a0a0a transparent transparent;border-right-style:solid;border-left-width:0;left:auto;right:100%}.top-bar{padding:.5rem}.top-bar:after,.top-bar:before{content:' ';display:table}.top-bar:after{clear:both}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{max-width:200px;margin-right:1rem}.top-bar .input-group-field{width:100%;margin-right:0}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{width:100%}@media screen and (min-width:40em){.top-bar .top-bar-left,.top-bar .top-bar-right{width:auto}}@media screen and (max-width:63.9375em){.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{width:100%}}@media screen and (max-width:74.9375em){.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{width:100%}}.top-bar-title{float:left;margin-right:1rem}.top-bar-left{float:left}.top-bar-right{float:right}.hide{display:none!important}.invisible{visibility:hidden}@media screen and (max-width:39.9375em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.9375em){.show-for-medium{display:none!important}}@media screen and (min-width:40em) and (max-width:63.9375em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.9375em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.9375em){.show-for-large{display:none!important}}@media screen and (min-width:64em) and (max-width:74.9375em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.9375em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}.show-on-focus:active,.show-on-focus:focus{position:static!important;height:auto;width:auto;overflow:visible;clip:auto}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{content:' ';display:table}.clearfix:after{clear:both} \ No newline at end of file diff --git a/sopds_web_backend/static/css/sopds.css b/sopds_web_backend/static/css/sopds.css new file mode 100644 index 0000000000000000000000000000000000000000..ca446d91c0958dad3a24405a7f0e0c350b0c4fe1 --- /dev/null +++ b/sopds_web_backend/static/css/sopds.css @@ -0,0 +1 @@ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:not-allowed}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{font-size:100%;box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}body{padding:0;margin:0;font-family:"Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;font-weight:normal;line-height:1.5;color:#0a0a0a;background:#fefefe;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}img{max-width:100%;height:auto;-ms-interpolation-mode:bicubic;display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px;border-radius:0}select{width:100%;border-radius:0}#map_canvas img,#map_canvas embed,#map_canvas object,.map_canvas img,.map_canvas embed,.map_canvas object,.mqa-display img,.mqa-display embed,.mqa-display object{max-width:none !important}button{-webkit-appearance:none;-moz-appearance:none;background:transparent;padding:0;border:0;border-radius:0;line-height:1}[data-whatinput='mouse'] button{outline:0}.is-visible{display:block !important}.is-hidden{display:none !important}.row{max-width:75rem;margin-left:auto;margin-right:auto}.row::before,.row::after{content:' ';display:table}.row::after{clear:both}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0}.row .row{margin-left:-.625rem;margin-right:-.625rem}@media screen and (min-width: 40em){.row .row{margin-left:-.9375rem;margin-right:-.9375rem}}.row .row.collapse{margin-left:0;margin-right:0}.row.expanded{max-width:none}.row.expanded .row{margin-left:auto;margin-right:auto}.column,.columns{width:100%;float:left;padding-left:.625rem;padding-right:.625rem}@media screen and (min-width: 40em){.column,.columns{padding-left:.9375rem;padding-right:.9375rem}}.column:last-child:not(:first-child),.columns:last-child:not(:first-child){float:right}.column.end:last-child:last-child,.end.columns:last-child:last-child{float:left}.column.row.row,.row.row.columns{float:none}.row .column.row.row,.row .row.row.columns{padding-left:0;padding-right:0;margin-left:0;margin-right:0}.small-1{width:8.33333%}.small-push-1{position:relative;left:8.33333%}.small-pull-1{position:relative;left:-8.33333%}.small-offset-0{margin-left:0%}.small-2{width:16.66667%}.small-push-2{position:relative;left:16.66667%}.small-pull-2{position:relative;left:-16.66667%}.small-offset-1{margin-left:8.33333%}.small-3{width:25%}.small-push-3{position:relative;left:25%}.small-pull-3{position:relative;left:-25%}.small-offset-2{margin-left:16.66667%}.small-4{width:33.33333%}.small-push-4{position:relative;left:33.33333%}.small-pull-4{position:relative;left:-33.33333%}.small-offset-3{margin-left:25%}.small-5{width:41.66667%}.small-push-5{position:relative;left:41.66667%}.small-pull-5{position:relative;left:-41.66667%}.small-offset-4{margin-left:33.33333%}.small-6{width:50%}.small-push-6{position:relative;left:50%}.small-pull-6{position:relative;left:-50%}.small-offset-5{margin-left:41.66667%}.small-7{width:58.33333%}.small-push-7{position:relative;left:58.33333%}.small-pull-7{position:relative;left:-58.33333%}.small-offset-6{margin-left:50%}.small-8{width:66.66667%}.small-push-8{position:relative;left:66.66667%}.small-pull-8{position:relative;left:-66.66667%}.small-offset-7{margin-left:58.33333%}.small-9{width:75%}.small-push-9{position:relative;left:75%}.small-pull-9{position:relative;left:-75%}.small-offset-8{margin-left:66.66667%}.small-10{width:83.33333%}.small-push-10{position:relative;left:83.33333%}.small-pull-10{position:relative;left:-83.33333%}.small-offset-9{margin-left:75%}.small-11{width:91.66667%}.small-push-11{position:relative;left:91.66667%}.small-pull-11{position:relative;left:-91.66667%}.small-offset-10{margin-left:83.33333%}.small-12{width:100%}.small-offset-11{margin-left:91.66667%}.small-up-1>.column,.small-up-1>.columns{width:100%;float:left}.small-up-1>.column:nth-of-type(1n),.small-up-1>.columns:nth-of-type(1n){clear:none}.small-up-1>.column:nth-of-type(1n+1),.small-up-1>.columns:nth-of-type(1n+1){clear:both}.small-up-1>.column:last-child,.small-up-1>.columns:last-child{float:left}.small-up-2>.column,.small-up-2>.columns{width:50%;float:left}.small-up-2>.column:nth-of-type(1n),.small-up-2>.columns:nth-of-type(1n){clear:none}.small-up-2>.column:nth-of-type(2n+1),.small-up-2>.columns:nth-of-type(2n+1){clear:both}.small-up-2>.column:last-child,.small-up-2>.columns:last-child{float:left}.small-up-3>.column,.small-up-3>.columns{width:33.33333%;float:left}.small-up-3>.column:nth-of-type(1n),.small-up-3>.columns:nth-of-type(1n){clear:none}.small-up-3>.column:nth-of-type(3n+1),.small-up-3>.columns:nth-of-type(3n+1){clear:both}.small-up-3>.column:last-child,.small-up-3>.columns:last-child{float:left}.small-up-4>.column,.small-up-4>.columns{width:25%;float:left}.small-up-4>.column:nth-of-type(1n),.small-up-4>.columns:nth-of-type(1n){clear:none}.small-up-4>.column:nth-of-type(4n+1),.small-up-4>.columns:nth-of-type(4n+1){clear:both}.small-up-4>.column:last-child,.small-up-4>.columns:last-child{float:left}.small-up-5>.column,.small-up-5>.columns{width:20%;float:left}.small-up-5>.column:nth-of-type(1n),.small-up-5>.columns:nth-of-type(1n){clear:none}.small-up-5>.column:nth-of-type(5n+1),.small-up-5>.columns:nth-of-type(5n+1){clear:both}.small-up-5>.column:last-child,.small-up-5>.columns:last-child{float:left}.small-up-6>.column,.small-up-6>.columns{width:16.66667%;float:left}.small-up-6>.column:nth-of-type(1n),.small-up-6>.columns:nth-of-type(1n){clear:none}.small-up-6>.column:nth-of-type(6n+1),.small-up-6>.columns:nth-of-type(6n+1){clear:both}.small-up-6>.column:last-child,.small-up-6>.columns:last-child{float:left}.small-up-7>.column,.small-up-7>.columns{width:14.28571%;float:left}.small-up-7>.column:nth-of-type(1n),.small-up-7>.columns:nth-of-type(1n){clear:none}.small-up-7>.column:nth-of-type(7n+1),.small-up-7>.columns:nth-of-type(7n+1){clear:both}.small-up-7>.column:last-child,.small-up-7>.columns:last-child{float:left}.small-up-8>.column,.small-up-8>.columns{width:12.5%;float:left}.small-up-8>.column:nth-of-type(1n),.small-up-8>.columns:nth-of-type(1n){clear:none}.small-up-8>.column:nth-of-type(8n+1),.small-up-8>.columns:nth-of-type(8n+1){clear:both}.small-up-8>.column:last-child,.small-up-8>.columns:last-child{float:left}.small-collapse>.column,.small-collapse>.columns{padding-left:0;padding-right:0}.small-collapse .row{margin-left:0;margin-right:0}.expanded.row .small-collapse.row{margin-left:0;margin-right:0}.small-uncollapse>.column,.small-uncollapse>.columns{padding-left:.625rem;padding-right:.625rem}.small-centered{margin-left:auto;margin-right:auto}.small-centered,.small-centered:last-child:not(:first-child){float:none;clear:both}.small-uncentered,.small-push-0,.small-pull-0{position:static;margin-left:0;margin-right:0;float:left}@media screen and (min-width: 40em){.medium-1{width:8.33333%}.medium-push-1{position:relative;left:8.33333%}.medium-pull-1{position:relative;left:-8.33333%}.medium-offset-0{margin-left:0%}.medium-2{width:16.66667%}.medium-push-2{position:relative;left:16.66667%}.medium-pull-2{position:relative;left:-16.66667%}.medium-offset-1{margin-left:8.33333%}.medium-3{width:25%}.medium-push-3{position:relative;left:25%}.medium-pull-3{position:relative;left:-25%}.medium-offset-2{margin-left:16.66667%}.medium-4{width:33.33333%}.medium-push-4{position:relative;left:33.33333%}.medium-pull-4{position:relative;left:-33.33333%}.medium-offset-3{margin-left:25%}.medium-5{width:41.66667%}.medium-push-5{position:relative;left:41.66667%}.medium-pull-5{position:relative;left:-41.66667%}.medium-offset-4{margin-left:33.33333%}.medium-6{width:50%}.medium-push-6{position:relative;left:50%}.medium-pull-6{position:relative;left:-50%}.medium-offset-5{margin-left:41.66667%}.medium-7{width:58.33333%}.medium-push-7{position:relative;left:58.33333%}.medium-pull-7{position:relative;left:-58.33333%}.medium-offset-6{margin-left:50%}.medium-8{width:66.66667%}.medium-push-8{position:relative;left:66.66667%}.medium-pull-8{position:relative;left:-66.66667%}.medium-offset-7{margin-left:58.33333%}.medium-9{width:75%}.medium-push-9{position:relative;left:75%}.medium-pull-9{position:relative;left:-75%}.medium-offset-8{margin-left:66.66667%}.medium-10{width:83.33333%}.medium-push-10{position:relative;left:83.33333%}.medium-pull-10{position:relative;left:-83.33333%}.medium-offset-9{margin-left:75%}.medium-11{width:91.66667%}.medium-push-11{position:relative;left:91.66667%}.medium-pull-11{position:relative;left:-91.66667%}.medium-offset-10{margin-left:83.33333%}.medium-12{width:100%}.medium-offset-11{margin-left:91.66667%}.medium-up-1>.column,.medium-up-1>.columns{width:100%;float:left}.medium-up-1>.column:nth-of-type(1n),.medium-up-1>.columns:nth-of-type(1n){clear:none}.medium-up-1>.column:nth-of-type(1n+1),.medium-up-1>.columns:nth-of-type(1n+1){clear:both}.medium-up-1>.column:last-child,.medium-up-1>.columns:last-child{float:left}.medium-up-2>.column,.medium-up-2>.columns{width:50%;float:left}.medium-up-2>.column:nth-of-type(1n),.medium-up-2>.columns:nth-of-type(1n){clear:none}.medium-up-2>.column:nth-of-type(2n+1),.medium-up-2>.columns:nth-of-type(2n+1){clear:both}.medium-up-2>.column:last-child,.medium-up-2>.columns:last-child{float:left}.medium-up-3>.column,.medium-up-3>.columns{width:33.33333%;float:left}.medium-up-3>.column:nth-of-type(1n),.medium-up-3>.columns:nth-of-type(1n){clear:none}.medium-up-3>.column:nth-of-type(3n+1),.medium-up-3>.columns:nth-of-type(3n+1){clear:both}.medium-up-3>.column:last-child,.medium-up-3>.columns:last-child{float:left}.medium-up-4>.column,.medium-up-4>.columns{width:25%;float:left}.medium-up-4>.column:nth-of-type(1n),.medium-up-4>.columns:nth-of-type(1n){clear:none}.medium-up-4>.column:nth-of-type(4n+1),.medium-up-4>.columns:nth-of-type(4n+1){clear:both}.medium-up-4>.column:last-child,.medium-up-4>.columns:last-child{float:left}.medium-up-5>.column,.medium-up-5>.columns{width:20%;float:left}.medium-up-5>.column:nth-of-type(1n),.medium-up-5>.columns:nth-of-type(1n){clear:none}.medium-up-5>.column:nth-of-type(5n+1),.medium-up-5>.columns:nth-of-type(5n+1){clear:both}.medium-up-5>.column:last-child,.medium-up-5>.columns:last-child{float:left}.medium-up-6>.column,.medium-up-6>.columns{width:16.66667%;float:left}.medium-up-6>.column:nth-of-type(1n),.medium-up-6>.columns:nth-of-type(1n){clear:none}.medium-up-6>.column:nth-of-type(6n+1),.medium-up-6>.columns:nth-of-type(6n+1){clear:both}.medium-up-6>.column:last-child,.medium-up-6>.columns:last-child{float:left}.medium-up-7>.column,.medium-up-7>.columns{width:14.28571%;float:left}.medium-up-7>.column:nth-of-type(1n),.medium-up-7>.columns:nth-of-type(1n){clear:none}.medium-up-7>.column:nth-of-type(7n+1),.medium-up-7>.columns:nth-of-type(7n+1){clear:both}.medium-up-7>.column:last-child,.medium-up-7>.columns:last-child{float:left}.medium-up-8>.column,.medium-up-8>.columns{width:12.5%;float:left}.medium-up-8>.column:nth-of-type(1n),.medium-up-8>.columns:nth-of-type(1n){clear:none}.medium-up-8>.column:nth-of-type(8n+1),.medium-up-8>.columns:nth-of-type(8n+1){clear:both}.medium-up-8>.column:last-child,.medium-up-8>.columns:last-child{float:left}.medium-collapse>.column,.medium-collapse>.columns{padding-left:0;padding-right:0}.medium-collapse .row{margin-left:0;margin-right:0}.expanded.row .medium-collapse.row{margin-left:0;margin-right:0}.medium-uncollapse>.column,.medium-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.medium-centered{margin-left:auto;margin-right:auto}.medium-centered,.medium-centered:last-child:not(:first-child){float:none;clear:both}.medium-uncentered,.medium-push-0,.medium-pull-0{position:static;margin-left:0;margin-right:0;float:left}}@media screen and (min-width: 64em){.large-1{width:8.33333%}.large-push-1{position:relative;left:8.33333%}.large-pull-1{position:relative;left:-8.33333%}.large-offset-0{margin-left:0%}.large-2{width:16.66667%}.large-push-2{position:relative;left:16.66667%}.large-pull-2{position:relative;left:-16.66667%}.large-offset-1{margin-left:8.33333%}.large-3{width:25%}.large-push-3{position:relative;left:25%}.large-pull-3{position:relative;left:-25%}.large-offset-2{margin-left:16.66667%}.large-4{width:33.33333%}.large-push-4{position:relative;left:33.33333%}.large-pull-4{position:relative;left:-33.33333%}.large-offset-3{margin-left:25%}.large-5{width:41.66667%}.large-push-5{position:relative;left:41.66667%}.large-pull-5{position:relative;left:-41.66667%}.large-offset-4{margin-left:33.33333%}.large-6{width:50%}.large-push-6{position:relative;left:50%}.large-pull-6{position:relative;left:-50%}.large-offset-5{margin-left:41.66667%}.large-7{width:58.33333%}.large-push-7{position:relative;left:58.33333%}.large-pull-7{position:relative;left:-58.33333%}.large-offset-6{margin-left:50%}.large-8{width:66.66667%}.large-push-8{position:relative;left:66.66667%}.large-pull-8{position:relative;left:-66.66667%}.large-offset-7{margin-left:58.33333%}.large-9{width:75%}.large-push-9{position:relative;left:75%}.large-pull-9{position:relative;left:-75%}.large-offset-8{margin-left:66.66667%}.large-10{width:83.33333%}.large-push-10{position:relative;left:83.33333%}.large-pull-10{position:relative;left:-83.33333%}.large-offset-9{margin-left:75%}.large-11{width:91.66667%}.large-push-11{position:relative;left:91.66667%}.large-pull-11{position:relative;left:-91.66667%}.large-offset-10{margin-left:83.33333%}.large-12{width:100%}.large-offset-11{margin-left:91.66667%}.large-up-1>.column,.large-up-1>.columns{width:100%;float:left}.large-up-1>.column:nth-of-type(1n),.large-up-1>.columns:nth-of-type(1n){clear:none}.large-up-1>.column:nth-of-type(1n+1),.large-up-1>.columns:nth-of-type(1n+1){clear:both}.large-up-1>.column:last-child,.large-up-1>.columns:last-child{float:left}.large-up-2>.column,.large-up-2>.columns{width:50%;float:left}.large-up-2>.column:nth-of-type(1n),.large-up-2>.columns:nth-of-type(1n){clear:none}.large-up-2>.column:nth-of-type(2n+1),.large-up-2>.columns:nth-of-type(2n+1){clear:both}.large-up-2>.column:last-child,.large-up-2>.columns:last-child{float:left}.large-up-3>.column,.large-up-3>.columns{width:33.33333%;float:left}.large-up-3>.column:nth-of-type(1n),.large-up-3>.columns:nth-of-type(1n){clear:none}.large-up-3>.column:nth-of-type(3n+1),.large-up-3>.columns:nth-of-type(3n+1){clear:both}.large-up-3>.column:last-child,.large-up-3>.columns:last-child{float:left}.large-up-4>.column,.large-up-4>.columns{width:25%;float:left}.large-up-4>.column:nth-of-type(1n),.large-up-4>.columns:nth-of-type(1n){clear:none}.large-up-4>.column:nth-of-type(4n+1),.large-up-4>.columns:nth-of-type(4n+1){clear:both}.large-up-4>.column:last-child,.large-up-4>.columns:last-child{float:left}.large-up-5>.column,.large-up-5>.columns{width:20%;float:left}.large-up-5>.column:nth-of-type(1n),.large-up-5>.columns:nth-of-type(1n){clear:none}.large-up-5>.column:nth-of-type(5n+1),.large-up-5>.columns:nth-of-type(5n+1){clear:both}.large-up-5>.column:last-child,.large-up-5>.columns:last-child{float:left}.large-up-6>.column,.large-up-6>.columns{width:16.66667%;float:left}.large-up-6>.column:nth-of-type(1n),.large-up-6>.columns:nth-of-type(1n){clear:none}.large-up-6>.column:nth-of-type(6n+1),.large-up-6>.columns:nth-of-type(6n+1){clear:both}.large-up-6>.column:last-child,.large-up-6>.columns:last-child{float:left}.large-up-7>.column,.large-up-7>.columns{width:14.28571%;float:left}.large-up-7>.column:nth-of-type(1n),.large-up-7>.columns:nth-of-type(1n){clear:none}.large-up-7>.column:nth-of-type(7n+1),.large-up-7>.columns:nth-of-type(7n+1){clear:both}.large-up-7>.column:last-child,.large-up-7>.columns:last-child{float:left}.large-up-8>.column,.large-up-8>.columns{width:12.5%;float:left}.large-up-8>.column:nth-of-type(1n),.large-up-8>.columns:nth-of-type(1n){clear:none}.large-up-8>.column:nth-of-type(8n+1),.large-up-8>.columns:nth-of-type(8n+1){clear:both}.large-up-8>.column:last-child,.large-up-8>.columns:last-child{float:left}.large-collapse>.column,.large-collapse>.columns{padding-left:0;padding-right:0}.large-collapse .row{margin-left:0;margin-right:0}.expanded.row .large-collapse.row{margin-left:0;margin-right:0}.large-uncollapse>.column,.large-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.large-centered{margin-left:auto;margin-right:auto}.large-centered,.large-centered:last-child:not(:first-child){float:none;clear:both}.large-uncentered,.large-push-0,.large-pull-0{position:static;margin-left:0;margin-right:0;float:left}}div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}p{font-size:inherit;line-height:1.6;margin-bottom:1rem;text-rendering:optimizeLegibility}em,i{font-style:italic;line-height:inherit}strong,b{font-weight:bold;line-height:inherit}small{font-size:80%;line-height:inherit}h1,h2,h3,h4,h5,h6{font-family:"Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;font-weight:normal;font-style:normal;color:inherit;text-rendering:optimizeLegibility;margin-top:0;margin-bottom:.5rem;line-height:1.4}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.1875rem}h4{font-size:1.125rem}h5{font-size:1.0625rem}h6{font-size:1rem}@media screen and (min-width: 40em){h1{font-size:3rem}h2{font-size:2.5rem}h3{font-size:1.9375rem}h4{font-size:1.5625rem}h5{font-size:1.25rem}h6{font-size:1rem}}a{color:#f15a23;text-decoration:none;line-height:inherit;cursor:pointer}a:hover,a:focus{color:#df460e}a img{border:0}hr{max-width:75rem;height:0;border-right:0;border-top:0;border-bottom:1px solid #cacaca;border-left:0;margin:1.25rem auto;clear:both}ul,ol,dl{line-height:1.6;margin-bottom:1rem;list-style-position:outside}li{font-size:inherit}ul{list-style-type:disc;margin-left:1.25rem}ol{margin-left:1.25rem}ul ul,ol ul,ul ol,ol ol{margin-left:1.25rem;margin-bottom:0}dl{margin-bottom:1rem}dl dt{margin-bottom:.3rem;font-weight:bold}blockquote{margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem;border-left:1px solid #cacaca}blockquote,blockquote p{line-height:1.6;color:#8a8a8a}cite{display:block;font-size:.8125rem;color:#8a8a8a}cite:before{content:'\2014 \0020'}abbr{color:#0a0a0a;cursor:help;border-bottom:1px dotted #0a0a0a}code{font-family:Consolas,"Liberation Mono",Courier,monospace;font-weight:normal;color:#0a0a0a;background-color:#e6e6e6;border:1px solid #cacaca;padding:.125rem .3125rem .0625rem}kbd{padding:.125rem .25rem 0;margin:0;background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,"Liberation Mono",Courier,monospace}.subheader{margin-top:.2rem;margin-bottom:.5rem;font-weight:normal;line-height:1.4;color:#8a8a8a}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}.no-bullet{margin-left:0;list-style:none}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media screen and (min-width: 40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media screen and (min-width: 64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none !important}@media print{*{background:transparent !important;color:black !important;box-shadow:none !important;text-shadow:none !important}.show-for-print{display:block !important}.hide-for-print{display:none !important}table.show-for-print{display:table !important}thead.show-for-print{display:table-header-group !important}tbody.show-for-print{display:table-row-group !important}tr.show-for-print{display:table-row !important}td.show-for-print{display:table-cell !important}th.show-for-print{display:table-cell !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^='javascript:']:after,a[href^='#']:after{content:''}abbr[title]:after{content:" (" attr(title) ")"}pre,blockquote{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.button{display:inline-block;text-align:center;line-height:1;cursor:pointer;-webkit-appearance:none;transition:background-color 0.25s ease-out, color 0.25s ease-out;vertical-align:middle;border:1px solid transparent;border-radius:0;padding:0.85em 1em;margin:0 0 1rem 0;font-size:0.9rem;background-color:#f15a23;color:#fefefe}[data-whatinput='mouse'] .button{outline:0}.button:hover,.button:focus{background-color:#dd450e;color:#fefefe}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;width:100%;margin-left:0;margin-right:0}.button.primary{background-color:#f15a23;color:#fefefe}.button.primary:hover,.button.primary:focus{background-color:#d0410d;color:#fefefe}.button.secondary{background-color:#777;color:#fefefe}.button.secondary:hover,.button.secondary:focus{background-color:#5f5f5f;color:#fefefe}.button.success{background-color:#3adb76;color:#fefefe}.button.success:hover,.button.success:focus{background-color:#22bb5b;color:#fefefe}.button.warning{background-color:#ffae00;color:#fefefe}.button.warning:hover,.button.warning:focus{background-color:#cc8b00;color:#fefefe}.button.alert{background-color:#ec5840;color:#fefefe}.button.alert:hover,.button.alert:focus{background-color:#da3116;color:#fefefe}.button.hollow{border:1px solid #f15a23;color:#f15a23}.button.hollow,.button.hollow:hover,.button.hollow:focus{background-color:transparent}.button.hollow:hover,.button.hollow:focus{border-color:#822908;color:#822908}.button.hollow.primary{border:1px solid #f15a23;color:#f15a23}.button.hollow.primary:hover,.button.hollow.primary:focus{border-color:#822908;color:#822908}.button.hollow.secondary{border:1px solid #777;color:#777}.button.hollow.secondary:hover,.button.hollow.secondary:focus{border-color:#3c3c3c;color:#3c3c3c}.button.hollow.success{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:hover,.button.hollow.success:focus{border-color:#157539;color:#157539}.button.hollow.warning{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:hover,.button.hollow.warning:focus{border-color:#805700;color:#805700}.button.hollow.alert{border:1px solid #ec5840;color:#ec5840}.button.hollow.alert:hover,.button.hollow.alert:focus{border-color:#881f0e;color:#881f0e}.button.disabled,.button[disabled]{opacity:.25;cursor:not-allowed}.button.disabled:hover,.button.disabled:focus,.button[disabled]:hover,.button[disabled]:focus{background-color:#f15a23;color:#fefefe}.button.disabled.primary,.button[disabled].primary{opacity:.25;cursor:not-allowed}.button.disabled.primary:hover,.button.disabled.primary:focus,.button[disabled].primary:hover,.button[disabled].primary:focus{background-color:#f15a23;color:#fefefe}.button.disabled.secondary,.button[disabled].secondary{opacity:.25;cursor:not-allowed}.button.disabled.secondary:hover,.button.disabled.secondary:focus,.button[disabled].secondary:hover,.button[disabled].secondary:focus{background-color:#777;color:#fefefe}.button.disabled.success,.button[disabled].success{opacity:.25;cursor:not-allowed}.button.disabled.success:hover,.button.disabled.success:focus,.button[disabled].success:hover,.button[disabled].success:focus{background-color:#3adb76;color:#fefefe}.button.disabled.warning,.button[disabled].warning{opacity:.25;cursor:not-allowed}.button.disabled.warning:hover,.button.disabled.warning:focus,.button[disabled].warning:hover,.button[disabled].warning:focus{background-color:#ffae00;color:#fefefe}.button.disabled.alert,.button[disabled].alert{opacity:.25;cursor:not-allowed}.button.disabled.alert:hover,.button.disabled.alert:focus,.button[disabled].alert:hover,.button[disabled].alert:focus{background-color:#ec5840;color:#fefefe}.button.dropdown::after{content:'';display:block;width:0;height:0;border:inset .4em;border-color:#fefefe transparent transparent;border-top-style:solid;border-bottom-width:0;position:relative;top:0.4em;float:right;margin-left:1em;display:inline-block}.button.arrow-only::after{margin-left:0;float:none;top:-0.1em}[type='text'],[type='password'],[type='date'],[type='datetime'],[type='datetime-local'],[type='month'],[type='week'],[type='email'],[type='number'],[type='search'],[type='tel'],[type='time'],[type='url'],[type='color'],textarea{display:block;box-sizing:border-box;width:100%;height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-family:inherit;font-size:1rem;color:#0a0a0a;background-color:#fefefe;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1);border-radius:0;transition:box-shadow 0.5s,border-color 0.25s ease-in-out;-webkit-appearance:none;-moz-appearance:none}[type='text']:focus,[type='password']:focus,[type='date']:focus,[type='datetime']:focus,[type='datetime-local']:focus,[type='month']:focus,[type='week']:focus,[type='email']:focus,[type='number']:focus,[type='search']:focus,[type='tel']:focus,[type='time']:focus,[type='url']:focus,[type='color']:focus,textarea:focus{border:1px solid #8a8a8a;background-color:#fefefe;outline:none;box-shadow:0 0 5px #cacaca;transition:box-shadow 0.5s,border-color 0.25s ease-in-out}textarea{max-width:100%}textarea[rows]{height:auto}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#cacaca}input::-moz-placeholder,textarea::-moz-placeholder{color:#cacaca}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#cacaca}input::placeholder,textarea::placeholder{color:#cacaca}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:default}[type='submit'],[type='button']{border-radius:0;-webkit-appearance:none;-moz-appearance:none}input[type='search']{box-sizing:border-box}[type='file'],[type='checkbox'],[type='radio']{margin:0 0 1rem}[type='checkbox']+label,[type='radio']+label{display:inline-block;margin-left:.5rem;margin-right:1rem;margin-bottom:0;vertical-align:baseline}[type='checkbox']+label[for],[type='radio']+label[for]{cursor:pointer}label>[type='checkbox'],label>[type='radio']{margin-right:.5rem}[type='file']{width:100%}label{display:block;margin:0;font-size:.875rem;font-weight:normal;line-height:1.8;color:#0a0a0a}label.middle{margin:0 0 1rem;padding:.5625rem 0}.help-text{margin-top:-.5rem;font-size:.8125rem;font-style:italic;color:#0a0a0a}.input-group{display:table;width:100%;margin-bottom:1rem}.input-group>:first-child{border-radius:0 0 0 0}.input-group>:last-child>*{border-radius:0 0 0 0}.input-group-label,.input-group-field,.input-group-button{margin:0;white-space:nowrap;display:table-cell;vertical-align:middle}.input-group-label{text-align:center;padding:0 1rem;background:#e6e6e6;color:#0a0a0a;border:1px solid #cacaca;white-space:nowrap;width:1%;height:100%}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{border-radius:0;height:2.5rem}.input-group-button{padding-top:0;padding-bottom:0;text-align:center;height:100%;width:1%}.input-group-button a,.input-group-button input,.input-group-button button{margin:0}.input-group .input-group-button{display:table-cell}fieldset{border:0;padding:0;margin:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;padding:1.25rem;margin:1.125rem 0}.fieldset legend{background:#fefefe;padding:0 .1875rem;margin:0;margin-left:-.1875rem}select{height:2.4375rem;padding:.5rem;border:1px solid #cacaca;margin:0 0 1rem;font-size:1rem;font-family:inherit;line-height:normal;color:#0a0a0a;background-color:#fefefe;border-radius:0;-webkit-appearance:none;-moz-appearance:none;background-image:url("data:image/svg+xml;utf8,");background-size:9px 6px;background-position:right -1rem center;background-origin:content-box;background-repeat:no-repeat;padding-right:1.5rem}@media screen and (min-width: 0\0){select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==")}}select:disabled{background-color:#e6e6e6;cursor:default}select::-ms-expand{display:none}select[multiple]{height:auto;background-image:none}.is-invalid-input:not(:focus){background-color:rgba(236,88,64,0.1);border-color:#ec5840}.is-invalid-label{color:#ec5840}.form-error{display:none;margin-top:-.5rem;margin-bottom:1rem;font-size:.75rem;font-weight:bold;color:#ec5840}.form-error.is-visible{display:block}.accordion{list-style-type:none;background:#fefefe;margin-left:0}.accordion-item:first-child>:first-child{border-radius:0 0 0 0}.accordion-item:last-child>:last-child{border-radius:0 0 0 0}.accordion-title{display:block;padding:1.25rem 1rem;line-height:1;font-size:.75rem;color:#f15a23;position:relative;border:1px solid #e6e6e6;border-bottom:0}:last-child:not(.is-active)>.accordion-title{border-radius:0 0 0 0;border-bottom:1px solid #e6e6e6}.accordion-title:hover,.accordion-title:focus{background-color:#e6e6e6}.accordion-title::before{content:'+';position:absolute;right:1rem;top:50%;margin-top:-0.5rem}.is-active>.accordion-title::before{content:'–'}.accordion-content{padding:1rem;display:none;border:1px solid #e6e6e6;border-bottom:0;background-color:#fefefe;color:#f15a23}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.is-accordion-submenu-parent>a{position:relative}.is-accordion-submenu-parent>a::after{content:'';display:block;width:0;height:0;border:inset 6px;border-color:#f15a23 transparent transparent;border-top-style:solid;border-bottom-width:0;position:absolute;top:50%;margin-top:-4px;right:1rem}.is-accordion-submenu-parent[aria-expanded='true']>a::after{-ms-transform-origin:50% 50%;transform-origin:50% 50%;-ms-transform:scaleY(-1);transform:scaleY(-1)}.badge{display:inline-block;padding:.3em;min-width:2.1em;font-size:.6rem;text-align:center;border-radius:50%;background:#f15a23;color:#fefefe}.badge.secondary{background:#777;color:#fefefe}.badge.success{background:#3adb76;color:#fefefe}.badge.warning{background:#ffae00;color:#fefefe}.badge.alert{background:#ec5840;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem 0}.breadcrumbs::before,.breadcrumbs::after{content:' ';display:table}.breadcrumbs::after{clear:both}.breadcrumbs li{float:left;color:#0a0a0a;font-size:.6875rem;cursor:default;text-transform:uppercase}.breadcrumbs li:not(:last-child)::after{color:#cacaca;content:"/";margin:0 .75rem;position:relative;top:1px;opacity:1}.breadcrumbs a{color:#f15a23}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.button-group{margin-bottom:1rem;font-size:0}.button-group::before,.button-group::after{content:' ';display:table}.button-group::after{clear:both}.button-group .button{margin:0;margin-right:1px;margin-bottom:1px;font-size:0.9rem}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded{margin-right:-1px}.button-group.expanded::before,.button-group.expanded::after{display:none}.button-group.expanded .button:first-child:nth-last-child(2),.button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button{display:inline-block;width:calc(50% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(2):last-child,.button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button:last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(3),.button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button{display:inline-block;width:calc(33.33333% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(3):last-child,.button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button:last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(4),.button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button{display:inline-block;width:calc(25% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(4):last-child,.button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button:last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(5),.button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button{display:inline-block;width:calc(20% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(5):last-child,.button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button:last-child{margin-right:-6px}.button-group.expanded .button:first-child:nth-last-child(6),.button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button{display:inline-block;width:calc(16.66667% - 1px);margin-right:1px}.button-group.expanded .button:first-child:nth-last-child(6):last-child,.button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button:last-child{margin-right:-6px}.button-group.primary .button{background-color:#f15a23;color:#fefefe}.button-group.primary .button:hover,.button-group.primary .button:focus{background-color:#d0410d;color:#fefefe}.button-group.secondary .button{background-color:#777;color:#fefefe}.button-group.secondary .button:hover,.button-group.secondary .button:focus{background-color:#5f5f5f;color:#fefefe}.button-group.success .button{background-color:#3adb76;color:#fefefe}.button-group.success .button:hover,.button-group.success .button:focus{background-color:#22bb5b;color:#fefefe}.button-group.warning .button{background-color:#ffae00;color:#fefefe}.button-group.warning .button:hover,.button-group.warning .button:focus{background-color:#cc8b00;color:#fefefe}.button-group.alert .button{background-color:#ec5840;color:#fefefe}.button-group.alert .button:hover,.button-group.alert .button:focus{background-color:#da3116;color:#fefefe}.button-group.stacked .button,.button-group.stacked-for-small .button,.button-group.stacked-for-medium .button{width:100%}.button-group.stacked .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked-for-medium .button:last-child{margin-bottom:0}@media screen and (min-width: 40em){.button-group.stacked-for-small .button{width:auto;margin-bottom:0}}@media screen and (min-width: 64em){.button-group.stacked-for-medium .button{width:auto;margin-bottom:0}}@media screen and (max-width: 39.9375em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}.callout{margin:0 0 1rem 0;padding:1rem;border:1px solid rgba(10,10,10,0.25);border-radius:0;position:relative;color:#0a0a0a;background-color:#fff}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#fde6de}.callout.secondary{background-color:#ebebeb}.callout.success{background-color:#e1faea}.callout.warning{background-color:#fff3d9}.callout.alert{background-color:#fce6e2}.callout.small{padding-top:.5rem;padding-right:.5rem;padding-bottom:.5rem;padding-left:.5rem}.callout.large{padding-top:3rem;padding-right:3rem;padding-bottom:3rem;padding-left:3rem}.close-button{position:absolute;color:#8a8a8a;right:1rem;top:.5rem;font-size:2em;line-height:1;cursor:pointer}[data-whatinput='mouse'] .close-button{outline:0}.close-button:hover,.close-button:focus{color:#0a0a0a}.menu{margin:0;list-style-type:none}.menu>li{display:table-cell;vertical-align:middle}[data-whatinput='mouse'] .menu>li{outline:0}.menu>li>a{display:block;padding:0.5rem 0.5rem;line-height:1}.menu input,.menu a,.menu button{margin-bottom:0}.menu>li>a img,.menu>li>a i,.menu>li>a svg{vertical-align:middle}.menu>li>a img+span,.menu>li>a i+span,.menu>li>a svg+span{vertical-align:middle}.menu>li>a img,.menu>li>a i,.menu>li>a svg{margin-right:.25rem;display:inline-block}.menu>li{display:table-cell}.menu.vertical>li{display:block}@media screen and (min-width: 40em){.menu.medium-horizontal>li{display:table-cell}.menu.medium-vertical>li{display:block}}@media screen and (min-width: 64em){.menu.large-horizontal>li{display:table-cell}.menu.large-vertical>li{display:block}}.menu.simple li{line-height:1;display:inline-block;margin-right:0.5rem}.menu.simple a{padding:0}.menu.align-right::before,.menu.align-right::after{content:' ';display:table}.menu.align-right::after{clear:both}.menu.align-right>li{float:right}.menu.expanded{width:100%;display:table;table-layout:fixed}.menu.expanded>li:first-child:last-child{width:100%}.menu.icon-top>li>a{text-align:center}.menu.icon-top>li>a img,.menu.icon-top>li>a i,.menu.icon-top>li>a svg{display:block;margin:0 auto .25rem}.menu.nested{margin-left:1rem}.menu .active>a{color:#fefefe;background:#d0410d}.menu-text{font-weight:bold;color:inherit;line-height:1;padding-top:0;padding-bottom:0;padding:0.5rem 0.5rem}.menu-centered{text-align:center}.menu-centered>.menu{display:inline-block}.no-js [data-responsive-menu] ul{display:none}.menu-icon{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon::after{content:'';position:absolute;display:block;width:100%;height:2px;background:#f15a23;top:0;left:0;box-shadow:0 7px 0 #f15a23,0 14px 0 #f15a23}.menu-icon:hover::after{background:#9c310a;box-shadow:0 7px 0 #9c310a,0 14px 0 #9c310a}.menu-icon.dark{position:relative;display:inline-block;vertical-align:middle;cursor:pointer;width:20px;height:16px}.menu-icon.dark::after{content:'';position:absolute;display:block;width:100%;height:2px;background:#0a0a0a;top:0;left:0;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a}.menu-icon.dark:hover::after{background:#8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.is-drilldown{position:relative;overflow:hidden}.is-drilldown li{display:block !important}.is-drilldown-submenu{position:absolute;top:0;left:100%;z-index:-1;width:100%;background:#fefefe;transition:transform 0.15s linear}.is-drilldown-submenu.is-active{z-index:1;display:block;-ms-transform:translateX(-100%);transform:translateX(-100%)}.is-drilldown-submenu.is-closing{-ms-transform:translateX(100%);transform:translateX(100%)}.is-drilldown-submenu-parent>a{position:relative}.is-drilldown-submenu-parent>a::after{content:'';display:block;width:0;height:0;border:inset 6px;border-color:transparent transparent transparent #f15a23;border-left-style:solid;border-right-width:0;position:absolute;top:50%;margin-top:-6px;right:1rem}.js-drilldown-back>a::before{content:'';display:block;width:0;height:0;border:inset 6px;border-color:transparent #f15a23 transparent transparent;border-right-style:solid;border-left-width:0;border-left-width:0;display:inline-block;vertical-align:middle;margin-right:0.75rem}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:block;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-open{visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}[data-whatinput='mouse'] .dropdown.menu a{outline:0}.no-js .dropdown.menu ul{display:none}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}@media screen and (min-width: 40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}}@media screen and (min-width: 64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{right:auto;left:0;top:100%}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{right:auto;left:100%}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{top:100%;left:auto;right:0}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a::after{position:absolute;top:50%;right:5px;margin-top:-2px}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{top:100%;left:auto}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{right:auto;left:100%}.is-dropdown-submenu{display:none;position:absolute;top:0;left:100%;min-width:200px;z-index:1;background:#fefefe;border:1px solid #cacaca}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.flex-video{position:relative;height:0;padding-bottom:75%;margin-bottom:1rem;overflow:hidden}.flex-video iframe,.flex-video object,.flex-video embed,.flex-video video{position:absolute;top:0;left:0;width:100%;height:100%}.flex-video.widescreen{padding-bottom:56.25%}.flex-video.vimeo{padding-top:0}.label{display:inline-block;padding:0.2rem 0.2rem;font-size:.8rem;line-height:1;white-space:nowrap;cursor:default;border-radius:0;background:#f15a23;color:#fefefe}.label.secondary{background:#777;color:#fefefe}.label.success{background:#3adb76;color:#fefefe}.label.warning{background:#ffae00;color:#fefefe}.label.alert{background:#ec5840;color:#fefefe}.media-object{margin-bottom:1rem;display:block}.media-object img{max-width:none}@media screen and (max-width: 39.9375em){.media-object.stack-for-small .media-object-section{padding:0;padding-bottom:1rem;display:block}.media-object.stack-for-small .media-object-section img{width:100%}}.media-object-section{display:table-cell;vertical-align:top}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}.media-object-section.middle{vertical-align:middle}.media-object-section.bottom{vertical-align:bottom}html,body{height:100%}.off-canvas-wrapper{width:100%;overflow-x:hidden;position:relative;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-overflow-scrolling:auto}.off-canvas-wrapper-inner{position:relative;width:100%;min-height:100%;transition:transform .5s ease}.off-canvas-wrapper-inner::before,.off-canvas-wrapper-inner::after{content:' ';display:table}.off-canvas-wrapper-inner::after{clear:both}.off-canvas-content,.off-canvas-content{min-height:100%;background:#fefefe;transition:transform .5s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1;padding-bottom:0.1px;box-shadow:0 0 10px rgba(10,10,10,0.5)}.js-off-canvas-exit{display:none;position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(254,254,254,0.25);cursor:pointer;transition:background .5s ease}.off-canvas{position:absolute;background:#e6e6e6;z-index:-1;max-height:100%;overflow-y:auto;-ms-transform:translateX(0);transform:translateX(0)}[data-whatinput='mouse'] .off-canvas{outline:0}.off-canvas.position-left{left:-250px;top:0;width:250px}.is-open-left{-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas.position-right{right:-250px;top:0;width:250px}.is-open-right{-ms-transform:translateX(-250px);transform:translateX(-250px)}@media screen and (min-width: 40em){.position-left.reveal-for-medium{left:0;z-index:auto;position:fixed}.position-left.reveal-for-medium ~ .off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{right:0;z-index:auto;position:fixed}.position-right.reveal-for-medium ~ .off-canvas-content{margin-right:250px}}@media screen and (min-width: 64em){.position-left.reveal-for-large{left:0;z-index:auto;position:fixed}.position-left.reveal-for-large ~ .off-canvas-content{margin-left:250px}.position-right.reveal-for-large{right:0;z-index:auto;position:fixed}.position-right.reveal-for-large ~ .off-canvas-content{margin-right:250px}}.orbit{position:relative}.orbit-container{position:relative;margin:0;overflow:hidden;list-style:none}.orbit-slide{width:100%;max-height:100%}.orbit-slide.no-motionui.is-active{top:0;left:0}.orbit-figure{margin:0}.orbit-image{margin:0;width:100%;max-width:100%}.orbit-caption{position:absolute;bottom:0;width:100%;padding:1rem;margin-bottom:0;color:#fefefe;background-color:rgba(10,10,10,0.5)}.orbit-previous,.orbit-next{position:absolute;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10;padding:1rem;color:#fefefe}[data-whatinput='mouse'] .orbit-previous,[data-whatinput='mouse'] .orbit-next{outline:0}.orbit-previous:hover,.orbit-next:hover,.orbit-previous:active,.orbit-next:active,.orbit-previous:focus,.orbit-next:focus{background-color:rgba(10,10,10,0.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{position:relative;margin-top:.8rem;margin-bottom:.8rem;text-align:center}[data-whatinput='mouse'] .orbit-bullets{outline:0}.orbit-bullets button{width:1.2rem;height:1.2rem;margin:.1rem;background-color:#cacaca;border-radius:50%}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.pagination{margin-left:0;margin-bottom:1rem}.pagination::before,.pagination::after{content:' ';display:table}.pagination::after{clear:both}.pagination li{font-size:.875rem;margin-right:.0625rem;border-radius:0;display:none}.pagination li:last-child,.pagination li:first-child{display:inline-block}@media screen and (min-width: 40em){.pagination li{display:inline-block}}.pagination a,.pagination button{color:#0a0a0a;display:block;padding:.1875rem .625rem;border-radius:0}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{padding:.1875rem .625rem;background:#f15a23;color:#fefefe;cursor:default}.pagination .disabled{padding:.1875rem .625rem;color:#cacaca;cursor:not-allowed}.pagination .disabled:hover{background:transparent}.pagination .ellipsis::after{content:'\2026';padding:.1875rem .625rem;color:#0a0a0a}.pagination-previous a::before,.pagination-previous.disabled::before{content:'\00ab';display:inline-block;margin-right:0.5rem}.pagination-next a::after,.pagination-next.disabled::after{content:'\00bb';display:inline-block;margin-left:0.5rem}.progress{background-color:#cacaca;height:1rem;margin-bottom:1rem;border-radius:0}.progress.primary .progress-meter{background-color:#f15a23}.progress.secondary .progress-meter{background-color:#777}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#ec5840}.progress-meter{position:relative;display:block;width:0%;height:100%;background-color:#f15a23}.progress-meter-text{position:absolute;top:50%;left:50%;-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);position:absolute;margin:0;font-size:0.75rem;font-weight:bold;color:#fefefe;white-space:nowrap}.slider{position:relative;height:.5rem;margin-top:1.25rem;margin-bottom:2.25rem;background-color:#e6e6e6;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-touch-action:none;touch-action:none}.slider-fill{position:absolute;top:0;left:0;display:inline-block;max-width:100%;height:.5rem;background-color:#cacaca;transition:all 0.2s ease-in-out}.slider-fill.is-dragging{transition:all 0s linear}.slider-handle{position:absolute;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);position:absolute;left:0;z-index:1;display:inline-block;width:1.4rem;height:1.4rem;background-color:#f15a23;transition:all 0.2s ease-in-out;-ms-touch-action:manipulation;touch-action:manipulation;border-radius:0}[data-whatinput='mouse'] .slider-handle{outline:0}.slider-handle:hover{background-color:#dd450e}.slider-handle.is-dragging{transition:all 0s linear}.slider.disabled,.slider[disabled]{opacity:.25;cursor:not-allowed}.slider.vertical{display:inline-block;width:.5rem;height:12.5rem;margin:0 1.25rem;-ms-transform:scale(1, -1);transform:scale(1, -1)}.slider.vertical .slider-fill{top:0;width:.5rem;max-height:100%}.slider.vertical .slider-handle{position:absolute;top:0;left:50%;width:1.4rem;height:1.4rem;-ms-transform:translateX(-50%);transform:translateX(-50%)}.sticky-container{position:relative}.sticky{position:absolute;z-index:0;transform:translate3d(0, 0, 0)}.sticky.is-stuck{position:fixed;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{position:absolute;left:auto;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}body.is-reveal-open{overflow:hidden}html.is-reveal-open,html.is-reveal-open body{min-height:100%;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.reveal-overlay{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:1005;background-color:rgba(10,10,10,0.45);overflow-y:scroll}.reveal{display:none;z-index:1006;padding:1rem;border:1px solid #cacaca;background-color:#fefefe;border-radius:0;position:relative;top:100px;margin-left:auto;margin-right:auto;overflow-y:auto}[data-whatinput='mouse'] .reveal{outline:0}@media screen and (min-width: 40em){.reveal{min-height:0}}.reveal .column,.reveal .columns,.reveal .columns{min-width:0}.reveal>:last-child{margin-bottom:0}@media screen and (min-width: 40em){.reveal{width:600px;max-width:75rem}}@media screen and (min-width: 40em){.reveal .reveal{left:auto;right:auto;margin:0 auto}}.reveal.collapse{padding:0}@media screen and (min-width: 40em){.reveal.tiny{width:30%;max-width:75rem}}@media screen and (min-width: 40em){.reveal.small{width:50%;max-width:75rem}}@media screen and (min-width: 40em){.reveal.large{width:90%;max-width:75rem}}.reveal.full{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}@media screen and (max-width: 39.9375em){.reveal{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}}.reveal.without-overlay{position:fixed}.switch{height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fefefe;font-weight:bold;font-size:.875rem}.switch-input{opacity:0;position:absolute;margin-bottom:0}.switch-paddle{background:#cacaca;cursor:pointer;display:block;position:relative;width:4rem;height:2rem;transition:all 0.25s ease-out;border-radius:0;color:inherit;font-weight:inherit}input+.switch-paddle{margin:0}.switch-paddle::after{background:#fefefe;content:'';display:block;position:absolute;height:1.5rem;left:0.25rem;top:0.25rem;width:1.5rem;transition:all 0.25s ease-out;transform:translate3d(0, 0, 0);border-radius:0}input:checked ~ .switch-paddle{background:#f15a23}input:checked ~ .switch-paddle::after{left:2.25rem}[data-whatinput='mouse'] input:focus ~ .switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{left:8%;display:none}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{width:3rem;height:1.5rem;font-size:.625rem}.switch.tiny .switch-paddle::after{width:1rem;height:1rem}.switch.tiny input:checked ~ .switch-paddle::after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{width:3.5rem;height:1.75rem;font-size:.75rem}.switch.small .switch-paddle::after{width:1.25rem;height:1.25rem}.switch.small input:checked ~ .switch-paddle::after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{width:5rem;height:2.5rem;font-size:1rem}.switch.large .switch-paddle::after{width:2rem;height:2rem}.switch.large input:checked ~ .switch-paddle::after{left:2.75rem}table{width:100%;margin-bottom:1rem;border-radius:0}table thead,table tbody,table tfoot{border:0px solid #f1f1f1;background-color:#fefefe}table caption{font-weight:bold;padding:.5rem .625rem .625rem}table thead{background:#f8f8f8;color:#0a0a0a}table tfoot{background:#f1f1f1;color:#0a0a0a}table thead tr,table tfoot tr{background:transparent}table thead th,table thead td,table tfoot th,table tfoot td{padding:.5rem .625rem .625rem;font-weight:bold;text-align:left}table tbody tr:nth-child(even){background-color:#f1f1f1}table tbody th,table tbody td{padding:.5rem .625rem .625rem}@media screen and (max-width: 63.9375em){table.stack thead{display:none}table.stack tfoot{display:none}table.stack tr,table.stack th,table.stack td{display:block}table.stack td{border-top:0}}table.scroll{display:block;width:100%;overflow-x:auto}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover tbody tr:nth-of-type(even):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.table-scroll table{width:auto}.tabs{margin:0;list-style-type:none;background:#fefefe;border:1px solid #e6e6e6}.tabs::before,.tabs::after{content:' ';display:table}.tabs::after{clear:both}.tabs.vertical>li{width:auto;float:none;display:block}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:transparent}.tabs.primary{background:#f15a23}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:hover,.tabs.primary>li>a:focus{background:#f05016}.tabs-title{float:left}.tabs-title>a{display:block;padding:1.25rem 1.5rem;line-height:1;font-size:.75rem}.tabs-title>a:hover{background:#fefefe}.tabs-title>a:focus,.tabs-title>a[aria-selected='true']{background:#e6e6e6}.tabs-content{background:#fefefe;transition:all 0.5s ease;border:1px solid #e6e6e6;border-top:0}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:solid 4px #fefefe;box-shadow:0 0 0 1px rgba(10,10,10,0.2);display:inline-block;line-height:0;max-width:100%;transition:box-shadow 200ms ease-out;border-radius:0;margin-bottom:1rem}.thumbnail:hover,.thumbnail:focus{box-shadow:0 0 6px 1px rgba(241,90,35,0.5)}.title-bar{background:#0a0a0a;color:#fefefe;padding:.5rem}.title-bar::before,.title-bar::after{content:' ';display:table}.title-bar::after{clear:both}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left{float:left}.title-bar-right{float:right;text-align:right}.title-bar-title{font-weight:bold;vertical-align:middle;display:inline-block}.has-tip{border-bottom:none 0px #8a8a8a;font-weight:bold;position:relative;display:inline-block;cursor:help}.tooltip{background-color:#0a0a0a;color:#fefefe;font-size:80%;padding:.75rem;position:absolute;z-index:10;top:calc(100% + .6495rem);max-width:10rem !important;border-radius:0}.tooltip::before{content:'';display:block;width:0;height:0;border:inset .75rem;border-color:transparent transparent #0a0a0a;border-bottom-style:solid;border-top-width:0;bottom:100%;position:absolute;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top::before{content:'';display:block;width:0;height:0;border:inset .75rem;border-color:#0a0a0a transparent transparent;border-top-style:solid;border-bottom-width:0;top:100%;bottom:auto}.tooltip.left::before{content:'';display:block;width:0;height:0;border:inset .75rem;border-color:transparent transparent transparent #0a0a0a;border-left-style:solid;border-right-width:0;bottom:auto;left:100%;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right::before{content:'';display:block;width:0;height:0;border:inset .75rem;border-color:transparent #0a0a0a transparent transparent;border-right-style:solid;border-left-width:0;bottom:auto;left:auto;right:100%;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%)}.top-bar{padding:.5rem}.top-bar::before,.top-bar::after{content:' ';display:table}.top-bar::after{clear:both}.top-bar,.top-bar ul{background-color:#fff}.top-bar input{max-width:200px;margin-right:1rem}.top-bar .input-group-field{width:100%;margin-right:0}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{width:100%}.top-bar .top-bar-left,.top-bar .top-bar-right{width:auto}@media screen and (max-width: 63.9375em){.stacked-for-medium.top-bar .top-bar-left,.stacked-for-medium.top-bar .top-bar-right{width:100%}}@media screen and (max-width: 74.9375em){.stacked-for-large.top-bar .top-bar-left,.stacked-for-large.top-bar .top-bar-right{width:100%}}.top-bar-title{float:left;margin-right:1rem}.top-bar-left{float:left}.top-bar-right{float:right}.hide{display:none !important}.invisible{visibility:hidden}@media screen and (max-width: 39.9375em){.hide-for-small-only{display:none !important}}@media screen and (max-width: 0em), screen and (min-width: 40em){.show-for-small-only{display:none !important}}@media screen and (min-width: 40em){.hide-for-medium{display:none !important}}@media screen and (max-width: 39.9375em){.show-for-medium{display:none !important}}@media screen and (min-width: 40em) and (max-width: 63.9375em){.hide-for-medium-only{display:none !important}}@media screen and (max-width: 39.9375em), screen and (min-width: 64em){.show-for-medium-only{display:none !important}}@media screen and (min-width: 64em){.hide-for-large{display:none !important}}@media screen and (max-width: 63.9375em){.show-for-large{display:none !important}}@media screen and (min-width: 64em) and (max-width: 74.9375em){.hide-for-large-only{display:none !important}}@media screen and (max-width: 63.9375em), screen and (min-width: 75em){.show-for-large-only{display:none !important}}.show-for-sr,.show-on-focus{position:absolute !important;width:1px;height:1px;overflow:hidden;clip:rect(0, 0, 0, 0)}.show-on-focus:active,.show-on-focus:focus{position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.show-for-landscape,.hide-for-portrait{display:block !important}@media screen and (orientation: landscape){.show-for-landscape,.hide-for-portrait{display:block !important}}@media screen and (orientation: portrait){.show-for-landscape,.hide-for-portrait{display:none !important}}.hide-for-landscape,.show-for-portrait{display:none !important}@media screen and (orientation: landscape){.hide-for-landscape,.show-for-portrait{display:none !important}}@media screen and (orientation: portrait){.hide-for-landscape,.show-for-portrait{display:block !important}}.float-left{float:left !important}.float-right{float:right !important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix::before,.clearfix::after{content:' ';display:table}.clearfix::after{clear:both}.slide-in-down.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateY(-100%);transform:translateY(-100%);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-in-down.mui-enter.mui-enter-active{-ms-transform:translateY(0);transform:translateY(0)}.slide-in-left.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateX(-100%);transform:translateX(-100%);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-in-left.mui-enter.mui-enter-active{-ms-transform:translateX(0);transform:translateX(0)}.slide-in-up.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateY(100%);transform:translateY(100%);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-in-up.mui-enter.mui-enter-active{-ms-transform:translateY(0);transform:translateY(0)}.slide-in-right.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateX(100%);transform:translateX(100%);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-in-right.mui-enter.mui-enter-active{-ms-transform:translateX(0);transform:translateX(0)}.slide-out-down.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateY(0);transform:translateY(0);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-out-down.mui-leave.mui-leave-active{-ms-transform:translateY(100%);transform:translateY(100%)}.slide-out-right.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateX(0);transform:translateX(0);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-out-right.mui-leave.mui-leave-active{-ms-transform:translateX(100%);transform:translateX(100%)}.slide-out-up.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateY(0);transform:translateY(0);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-out-up.mui-leave.mui-leave-active{-ms-transform:translateY(-100%);transform:translateY(-100%)}.slide-out-left.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:translateX(0);transform:translateX(0);transition-property:transform, opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden}.slide-out-left.mui-leave.mui-leave-active{-ms-transform:translateX(-100%);transform:translateX(-100%)}.fade-in.mui-enter{transition-duration:500ms;transition-timing-function:linear;opacity:0;transition-property:opacity}.fade-in.mui-enter.mui-enter-active{opacity:1}.fade-out.mui-leave{transition-duration:500ms;transition-timing-function:linear;opacity:1;transition-property:opacity}.fade-out.mui-leave.mui-leave-active{opacity:0}.hinge-in-from-top.mui-enter{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotateX(-90deg);-ms-transform-origin:top;transform-origin:top;transition-property:transform, opacity;opacity:0}.hinge-in-from-top.mui-enter.mui-enter-active{transform:perspective(2000px) rotate(0deg);opacity:1}.hinge-in-from-right.mui-enter{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotateY(-90deg);-ms-transform-origin:right;transform-origin:right;transition-property:transform, opacity;opacity:0}.hinge-in-from-right.mui-enter.mui-enter-active{transform:perspective(2000px) rotate(0deg);opacity:1}.hinge-in-from-bottom.mui-enter{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotateX(90deg);-ms-transform-origin:bottom;transform-origin:bottom;transition-property:transform, opacity;opacity:0}.hinge-in-from-bottom.mui-enter.mui-enter-active{transform:perspective(2000px) rotate(0deg);opacity:1}.hinge-in-from-left.mui-enter{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotateY(90deg);-ms-transform-origin:left;transform-origin:left;transition-property:transform, opacity;opacity:0}.hinge-in-from-left.mui-enter.mui-enter-active{transform:perspective(2000px) rotate(0deg);opacity:1}.hinge-in-from-middle-x.mui-enter{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotateX(-90deg);-ms-transform-origin:center;transform-origin:center;transition-property:transform, opacity;opacity:0}.hinge-in-from-middle-x.mui-enter.mui-enter-active{transform:perspective(2000px) rotate(0deg);opacity:1}.hinge-in-from-middle-y.mui-enter{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotateY(-90deg);-ms-transform-origin:center;transform-origin:center;transition-property:transform, opacity;opacity:0}.hinge-in-from-middle-y.mui-enter.mui-enter-active{transform:perspective(2000px) rotate(0deg);opacity:1}.hinge-out-from-top.mui-leave{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotate(0deg);-ms-transform-origin:top;transform-origin:top;transition-property:transform, opacity;opacity:1}.hinge-out-from-top.mui-leave.mui-leave-active{transform:perspective(2000px) rotateX(-90deg);opacity:0}.hinge-out-from-right.mui-leave{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotate(0deg);-ms-transform-origin:right;transform-origin:right;transition-property:transform, opacity;opacity:1}.hinge-out-from-right.mui-leave.mui-leave-active{transform:perspective(2000px) rotateY(-90deg);opacity:0}.hinge-out-from-bottom.mui-leave{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotate(0deg);-ms-transform-origin:bottom;transform-origin:bottom;transition-property:transform, opacity;opacity:1}.hinge-out-from-bottom.mui-leave.mui-leave-active{transform:perspective(2000px) rotateX(90deg);opacity:0}.hinge-out-from-left.mui-leave{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotate(0deg);-ms-transform-origin:left;transform-origin:left;transition-property:transform, opacity;opacity:1}.hinge-out-from-left.mui-leave.mui-leave-active{transform:perspective(2000px) rotateY(90deg);opacity:0}.hinge-out-from-middle-x.mui-leave{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotate(0deg);-ms-transform-origin:center;transform-origin:center;transition-property:transform, opacity;opacity:1}.hinge-out-from-middle-x.mui-leave.mui-leave-active{transform:perspective(2000px) rotateX(-90deg);opacity:0}.hinge-out-from-middle-y.mui-leave{transition-duration:500ms;transition-timing-function:linear;transform:perspective(2000px) rotate(0deg);-ms-transform-origin:center;transform-origin:center;transition-property:transform, opacity;opacity:1}.hinge-out-from-middle-y.mui-leave.mui-leave-active{transform:perspective(2000px) rotateY(-90deg);opacity:0}.scale-in-up.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:scale(.5);transform:scale(.5);transition-property:transform, opacity;opacity:0}.scale-in-up.mui-enter.mui-enter-active{-ms-transform:scale(1);transform:scale(1);opacity:1}.scale-in-down.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:scale(1.5);transform:scale(1.5);transition-property:transform, opacity;opacity:0}.scale-in-down.mui-enter.mui-enter-active{-ms-transform:scale(1);transform:scale(1);opacity:1}.scale-out-up.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:scale(1);transform:scale(1);transition-property:transform, opacity;opacity:1}.scale-out-up.mui-leave.mui-leave-active{-ms-transform:scale(1.5);transform:scale(1.5);opacity:0}.scale-out-down.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:scale(1);transform:scale(1);transition-property:transform, opacity;opacity:1}.scale-out-down.mui-leave.mui-leave-active{-ms-transform:scale(.5);transform:scale(.5);opacity:0}.spin-in.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:rotate(-.75turn);transform:rotate(-.75turn);transition-property:transform, opacity;opacity:0}.spin-in.mui-enter.mui-enter-active{-ms-transform:rotate(0);transform:rotate(0);opacity:1}.spin-out.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:rotate(0);transform:rotate(0);transition-property:transform, opacity;opacity:1}.spin-out.mui-leave.mui-leave-active{-ms-transform:rotate(.75turn);transform:rotate(.75turn);opacity:0}.spin-in-ccw.mui-enter{transition-duration:500ms;transition-timing-function:linear;-ms-transform:rotate(.75turn);transform:rotate(.75turn);transition-property:transform, opacity;opacity:0}.spin-in-ccw.mui-enter.mui-enter-active{-ms-transform:rotate(0);transform:rotate(0);opacity:1}.spin-out-ccw.mui-leave{transition-duration:500ms;transition-timing-function:linear;-ms-transform:rotate(0);transform:rotate(0);transition-property:transform, opacity;opacity:1}.spin-out-ccw.mui-leave.mui-leave-active{-ms-transform:rotate(-.75turn);transform:rotate(-.75turn);opacity:0}.slow{transition-duration:750ms !important}.fast{transition-duration:250ms !important}.linear{transition-timing-function:linear !important}.ease{transition-timing-function:ease !important}.ease-in{transition-timing-function:ease-in !important}.ease-out{transition-timing-function:ease-out !important}.ease-in-out{transition-timing-function:ease-in-out !important}.bounce-in{transition-timing-function:cubic-bezier(0.485, 0.155, 0.24, 1.245) !important}.bounce-out{transition-timing-function:cubic-bezier(0.485, 0.155, 0.515, 0.845) !important}.bounce-in-out{transition-timing-function:cubic-bezier(0.76, -0.245, 0.24, 1.245) !important}.short-delay{transition-delay:300ms !important}.long-delay{transition-delay:700ms !important}.shake{animation-name:shake-7}@keyframes shake-7{0%,10%,20%,30%,40%,50%,60%,70%,80%,90%{transform:translateX(7%)}5%,15%,25%,35%,45%,55%,65%,75%,85%,95%{transform:translateX(-7%)}}.spin-cw{animation-name:spin-cw-1turn}@keyframes spin-cw-1turn{0%{transform:rotate(-1turn)}100%{transform:rotate(0)}}.spin-ccw{animation-name:spin-cw-1turn}@keyframes spin-cw-1turn{0%{transform:rotate(0)}100%{transform:rotate(1turn)}}.wiggle{animation-name:wiggle-7deg}@keyframes wiggle-7deg{40%,50%,60%{transform:rotate(7deg)}35%,45%,55%,65%{transform:rotate(-7deg)}0%,30%,70%,100%{transform:rotate(0)}}.shake,.spin-cw,.spin-ccw,.wiggle{animation-duration:500ms}.infinite{animation-iteration-count:infinite}.slow{animation-duration:750ms !important}.fast{animation-duration:250ms !important}.linear{animation-timing-function:linear !important}.ease{animation-timing-function:ease !important}.ease-in{animation-timing-function:ease-in !important}.ease-out{animation-timing-function:ease-out !important}.ease-in-out{animation-timing-function:ease-in-out !important}.bounce-in{animation-timing-function:cubic-bezier(0.485, 0.155, 0.24, 1.245) !important}.bounce-out{animation-timing-function:cubic-bezier(0.485, 0.155, 0.515, 0.845) !important}.bounce-in-out{animation-timing-function:cubic-bezier(0.76, -0.245, 0.24, 1.245) !important}.short-delay{animation-delay:300ms !important}.long-delay{animation-delay:700ms !important}.top-bar ul.menu a{color:#f15a23}.top-bar ul.menu a:hover{color:#9c310a}.top-bar .title-bar-title{color:#f15a23}.sopdsbg{background-color:#f15a23;color:#f15a23}.sopdsbg a{color:#f15a23}.sopdsbg a:hover{color:#9c310a}.sopdsmenu{background-color:#f15a23;color:#fff}.sopdsmenu a{color:#fff}.sopdsmenu a:hover{background-color:#dd450e} diff --git a/sopds_web_backend/static/foundation-icons/.DS_Store b/sopds_web_backend/static/foundation-icons/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b7f17920bfe26f0d78d63316d70e9c60cec14b56 Binary files /dev/null and b/sopds_web_backend/static/foundation-icons/.DS_Store differ diff --git a/sopds_web_backend/static/foundation-icons/.fontcustom-data b/sopds_web_backend/static/foundation-icons/.fontcustom-data new file mode 100644 index 0000000000000000000000000000000000000000..8753d7b15f6a8bc974549a0414b1ffa521cec2a1 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/.fontcustom-data @@ -0,0 +1,298 @@ +{ + "fonts": [ + "fontcustom_10588e4d0af9f9cd5471c9540658204b.ttf", + "fontcustom_10588e4d0af9f9cd5471c9540658204b.woff", + "fontcustom_10588e4d0af9f9cd5471c9540658204b.eot", + "fontcustom_10588e4d0af9f9cd5471c9540658204b.svg" + ], + "templates": [ + "fontcustom.css", + "fontcustom-preview.html" + ], + "file_name": "fontcustom_10588e4d0af9f9cd5471c9540658204b", + "glyphs": [ + "fi-address-book", + "fi-alert", + "fi-align-center", + "fi-align-justify", + "fi-align-left", + "fi-align-right", + "fi-anchor", + "fi-annotate", + "fi-archive", + "fi-arrow-down", + "fi-arrow-left", + "fi-arrow-right", + "fi-arrow-up", + "fi-arrows-compress", + "fi-arrows-expand", + "fi-arrows-in", + "fi-arrows-out", + "fi-asl", + "fi-asterisk", + "fi-at-sign", + "fi-background-color", + "fi-battery-empty", + "fi-battery-full", + "fi-battery-half", + "fi-bitcoin-circle", + "fi-bitcoin", + "fi-blind", + "fi-bluetooth", + "fi-bold", + "fi-book-bookmark", + "fi-book", + "fi-bookmark", + "fi-braille", + "fi-burst-new", + "fi-burst-sale", + "fi-burst", + "fi-calendar", + "fi-camera", + "fi-check", + "fi-checkbox", + "fi-clipboard-notes", + "fi-clipboard-pencil", + "fi-clipboard", + "fi-clock", + "fi-closed-caption", + "fi-cloud", + "fi-comment-minus", + "fi-comment-quotes", + "fi-comment-video", + "fi-comment", + "fi-comments", + "fi-compass", + "fi-contrast", + "fi-credit-card", + "fi-crop", + "fi-crown", + "fi-css3", + "fi-database", + "fi-die-five", + "fi-die-four", + "fi-die-one", + "fi-die-six", + "fi-die-three", + "fi-die-two", + "fi-dislike", + "fi-dollar-bill", + "fi-dollar", + "fi-download", + "fi-eject", + "fi-elevator", + "fi-euro", + "fi-eye", + "fi-fast-forward", + "fi-female-symbol", + "fi-female", + "fi-filter", + "fi-first-aid", + "fi-flag", + "fi-folder-add", + "fi-folder-lock", + "fi-folder", + "fi-foot", + "fi-foundation", + "fi-graph-bar", + "fi-graph-horizontal", + "fi-graph-pie", + "fi-graph-trend", + "fi-guide-dog", + "fi-hearing-aid", + "fi-heart", + "fi-home", + "fi-html5", + "fi-indent-less", + "fi-indent-more", + "fi-info", + "fi-italic", + "fi-key", + "fi-laptop", + "fi-layout", + "fi-lightbulb", + "fi-like", + "fi-link", + "fi-list-bullet", + "fi-list-number", + "fi-list-thumbnails", + "fi-list", + "fi-lock", + "fi-loop", + "fi-magnifying-glass", + "fi-mail", + "fi-male-female", + "fi-male-symbol", + "fi-male", + "fi-map", + "fi-marker", + "fi-megaphone", + "fi-microphone", + "fi-minus-circle", + "fi-minus", + "fi-mobile-signal", + "fi-mobile", + "fi-monitor", + "fi-mountains", + "fi-music", + "fi-next", + "fi-no-dogs", + "fi-no-smoking", + "fi-page-add", + "fi-page-copy", + "fi-page-csv", + "fi-page-delete", + "fi-page-doc", + "fi-page-edit", + "fi-page-export-csv", + "fi-page-export-doc", + "fi-page-export-pdf", + "fi-page-export", + "fi-page-filled", + "fi-page-multiple", + "fi-page-pdf", + "fi-page-remove", + "fi-page-search", + "fi-page", + "fi-paint-bucket", + "fi-paperclip", + "fi-pause", + "fi-paw", + "fi-paypal", + "fi-pencil", + "fi-photo", + "fi-play-circle", + "fi-play-video", + "fi-play", + "fi-plus", + "fi-pound", + "fi-power", + "fi-previous", + "fi-price-tag", + "fi-pricetag-multiple", + "fi-print", + "fi-prohibited", + "fi-projection-screen", + "fi-puzzle", + "fi-quote", + "fi-record", + "fi-refresh", + "fi-results-demographics", + "fi-results", + "fi-rewind-ten", + "fi-rewind", + "fi-rss", + "fi-safety-cone", + "fi-save", + "fi-share", + "fi-sheriff-badge", + "fi-shield", + "fi-shopping-bag", + "fi-shopping-cart", + "fi-shuffle", + "fi-skull", + "fi-social-500px", + "fi-social-adobe", + "fi-social-amazon", + "fi-social-android", + "fi-social-apple", + "fi-social-behance", + "fi-social-bing", + "fi-social-blogger", + "fi-social-delicious", + "fi-social-designer-news", + "fi-social-deviant-art", + "fi-social-digg", + "fi-social-dribbble", + "fi-social-drive", + "fi-social-dropbox", + "fi-social-evernote", + "fi-social-facebook", + "fi-social-flickr", + "fi-social-forrst", + "fi-social-foursquare", + "fi-social-game-center", + "fi-social-github", + "fi-social-google-plus", + "fi-social-hacker-news", + "fi-social-hi5", + "fi-social-instagram", + "fi-social-joomla", + "fi-social-lastfm", + "fi-social-linkedin", + "fi-social-medium", + "fi-social-myspace", + "fi-social-orkut", + "fi-social-path", + "fi-social-picasa", + "fi-social-pinterest", + "fi-social-rdio", + "fi-social-reddit", + "fi-social-skillshare", + "fi-social-skype", + "fi-social-smashing-mag", + "fi-social-snapchat", + "fi-social-spotify", + "fi-social-squidoo", + "fi-social-stack-overflow", + "fi-social-steam", + "fi-social-stumbleupon", + "fi-social-treehouse", + "fi-social-tumblr", + "fi-social-twitter", + "fi-social-vimeo", + "fi-social-windows", + "fi-social-xbox-20", + "fi-social-yahoo", + "fi-social-yelp", + "fi-social-youtube", + "fi-social-zerply", + "fi-social-zurb", + "fi-sound", + "fi-star", + "fi-stop", + "fi-strikethrough", + "fi-subscript", + "fi-superscript", + "fi-tablet-landscape", + "fi-tablet-portrait", + "fi-target-two", + "fi-target", + "fi-telephone-accessible", + "fi-telephone", + "fi-text-color", + "fi-thumbnails", + "fi-ticket", + "fi-torso-business", + "fi-torso-female", + "fi-torso", + "fi-torsos-all-female", + "fi-torsos-all", + "fi-torsos-female-male", + "fi-torsos-male-female", + "fi-torsos", + "fi-trash", + "fi-trees", + "fi-trophy", + "fi-underline", + "fi-universal-access", + "fi-unlink", + "fi-unlock", + "fi-upload-cloud", + "fi-upload", + "fi-usb", + "fi-video", + "fi-volume-none", + "fi-volume-strike", + "fi-volume", + "fi-web", + "fi-wheelchair", + "fi-widget", + "fi-wrench", + "fi-x-circle", + "fi-x", + "fi-yen", + "fi-zoom-in", + "fi-zoom-out" + ] +} \ No newline at end of file diff --git a/sopds_web_backend/static/foundation-icons/foundation-icons.css b/sopds_web_backend/static/foundation-icons/foundation-icons.css new file mode 100644 index 0000000000000000000000000000000000000000..d866a73352494020724b8868a05c474ae0937148 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/foundation-icons.css @@ -0,0 +1,594 @@ +/* + * Foundation Icons v 3.0 + * Made by ZURB 2013 http://zurb.com/playground/foundation-icon-fonts-3 + * MIT License + */ + +@font-face { + font-family: "foundation-icons"; + src: url("foundation-icons.eot"); + src: url("foundation-icons.eot?#iefix") format("embedded-opentype"), + url("foundation-icons.woff") format("woff"), + url("foundation-icons.ttf") format("truetype"), + url("foundation-icons.svg#fontcustom") format("svg"); + font-weight: normal; + font-style: normal; +} + +.fi-address-book:before, +.fi-alert:before, +.fi-align-center:before, +.fi-align-justify:before, +.fi-align-left:before, +.fi-align-right:before, +.fi-anchor:before, +.fi-annotate:before, +.fi-archive:before, +.fi-arrow-down:before, +.fi-arrow-left:before, +.fi-arrow-right:before, +.fi-arrow-up:before, +.fi-arrows-compress:before, +.fi-arrows-expand:before, +.fi-arrows-in:before, +.fi-arrows-out:before, +.fi-asl:before, +.fi-asterisk:before, +.fi-at-sign:before, +.fi-background-color:before, +.fi-battery-empty:before, +.fi-battery-full:before, +.fi-battery-half:before, +.fi-bitcoin-circle:before, +.fi-bitcoin:before, +.fi-blind:before, +.fi-bluetooth:before, +.fi-bold:before, +.fi-book-bookmark:before, +.fi-book:before, +.fi-bookmark:before, +.fi-braille:before, +.fi-burst-new:before, +.fi-burst-sale:before, +.fi-burst:before, +.fi-calendar:before, +.fi-camera:before, +.fi-check:before, +.fi-checkbox:before, +.fi-clipboard-notes:before, +.fi-clipboard-pencil:before, +.fi-clipboard:before, +.fi-clock:before, +.fi-closed-caption:before, +.fi-cloud:before, +.fi-comment-minus:before, +.fi-comment-quotes:before, +.fi-comment-video:before, +.fi-comment:before, +.fi-comments:before, +.fi-compass:before, +.fi-contrast:before, +.fi-credit-card:before, +.fi-crop:before, +.fi-crown:before, +.fi-css3:before, +.fi-database:before, +.fi-die-five:before, +.fi-die-four:before, +.fi-die-one:before, +.fi-die-six:before, +.fi-die-three:before, +.fi-die-two:before, +.fi-dislike:before, +.fi-dollar-bill:before, +.fi-dollar:before, +.fi-download:before, +.fi-eject:before, +.fi-elevator:before, +.fi-euro:before, +.fi-eye:before, +.fi-fast-forward:before, +.fi-female-symbol:before, +.fi-female:before, +.fi-filter:before, +.fi-first-aid:before, +.fi-flag:before, +.fi-folder-add:before, +.fi-folder-lock:before, +.fi-folder:before, +.fi-foot:before, +.fi-foundation:before, +.fi-graph-bar:before, +.fi-graph-horizontal:before, +.fi-graph-pie:before, +.fi-graph-trend:before, +.fi-guide-dog:before, +.fi-hearing-aid:before, +.fi-heart:before, +.fi-home:before, +.fi-html5:before, +.fi-indent-less:before, +.fi-indent-more:before, +.fi-info:before, +.fi-italic:before, +.fi-key:before, +.fi-laptop:before, +.fi-layout:before, +.fi-lightbulb:before, +.fi-like:before, +.fi-link:before, +.fi-list-bullet:before, +.fi-list-number:before, +.fi-list-thumbnails:before, +.fi-list:before, +.fi-lock:before, +.fi-loop:before, +.fi-magnifying-glass:before, +.fi-mail:before, +.fi-male-female:before, +.fi-male-symbol:before, +.fi-male:before, +.fi-map:before, +.fi-marker:before, +.fi-megaphone:before, +.fi-microphone:before, +.fi-minus-circle:before, +.fi-minus:before, +.fi-mobile-signal:before, +.fi-mobile:before, +.fi-monitor:before, +.fi-mountains:before, +.fi-music:before, +.fi-next:before, +.fi-no-dogs:before, +.fi-no-smoking:before, +.fi-page-add:before, +.fi-page-copy:before, +.fi-page-csv:before, +.fi-page-delete:before, +.fi-page-doc:before, +.fi-page-edit:before, +.fi-page-export-csv:before, +.fi-page-export-doc:before, +.fi-page-export-pdf:before, +.fi-page-export:before, +.fi-page-filled:before, +.fi-page-multiple:before, +.fi-page-pdf:before, +.fi-page-remove:before, +.fi-page-search:before, +.fi-page:before, +.fi-paint-bucket:before, +.fi-paperclip:before, +.fi-pause:before, +.fi-paw:before, +.fi-paypal:before, +.fi-pencil:before, +.fi-photo:before, +.fi-play-circle:before, +.fi-play-video:before, +.fi-play:before, +.fi-plus:before, +.fi-pound:before, +.fi-power:before, +.fi-previous:before, +.fi-price-tag:before, +.fi-pricetag-multiple:before, +.fi-print:before, +.fi-prohibited:before, +.fi-projection-screen:before, +.fi-puzzle:before, +.fi-quote:before, +.fi-record:before, +.fi-refresh:before, +.fi-results-demographics:before, +.fi-results:before, +.fi-rewind-ten:before, +.fi-rewind:before, +.fi-rss:before, +.fi-safety-cone:before, +.fi-save:before, +.fi-share:before, +.fi-sheriff-badge:before, +.fi-shield:before, +.fi-shopping-bag:before, +.fi-shopping-cart:before, +.fi-shuffle:before, +.fi-skull:before, +.fi-social-500px:before, +.fi-social-adobe:before, +.fi-social-amazon:before, +.fi-social-android:before, +.fi-social-apple:before, +.fi-social-behance:before, +.fi-social-bing:before, +.fi-social-blogger:before, +.fi-social-delicious:before, +.fi-social-designer-news:before, +.fi-social-deviant-art:before, +.fi-social-digg:before, +.fi-social-dribbble:before, +.fi-social-drive:before, +.fi-social-dropbox:before, +.fi-social-evernote:before, +.fi-social-facebook:before, +.fi-social-flickr:before, +.fi-social-forrst:before, +.fi-social-foursquare:before, +.fi-social-game-center:before, +.fi-social-github:before, +.fi-social-google-plus:before, +.fi-social-hacker-news:before, +.fi-social-hi5:before, +.fi-social-instagram:before, +.fi-social-joomla:before, +.fi-social-lastfm:before, +.fi-social-linkedin:before, +.fi-social-medium:before, +.fi-social-myspace:before, +.fi-social-orkut:before, +.fi-social-path:before, +.fi-social-picasa:before, +.fi-social-pinterest:before, +.fi-social-rdio:before, +.fi-social-reddit:before, +.fi-social-skillshare:before, +.fi-social-skype:before, +.fi-social-smashing-mag:before, +.fi-social-snapchat:before, +.fi-social-spotify:before, +.fi-social-squidoo:before, +.fi-social-stack-overflow:before, +.fi-social-steam:before, +.fi-social-stumbleupon:before, +.fi-social-treehouse:before, +.fi-social-tumblr:before, +.fi-social-twitter:before, +.fi-social-vimeo:before, +.fi-social-windows:before, +.fi-social-xbox:before, +.fi-social-yahoo:before, +.fi-social-yelp:before, +.fi-social-youtube:before, +.fi-social-zerply:before, +.fi-social-zurb:before, +.fi-sound:before, +.fi-star:before, +.fi-stop:before, +.fi-strikethrough:before, +.fi-subscript:before, +.fi-superscript:before, +.fi-tablet-landscape:before, +.fi-tablet-portrait:before, +.fi-target-two:before, +.fi-target:before, +.fi-telephone-accessible:before, +.fi-telephone:before, +.fi-text-color:before, +.fi-thumbnails:before, +.fi-ticket:before, +.fi-torso-business:before, +.fi-torso-female:before, +.fi-torso:before, +.fi-torsos-all-female:before, +.fi-torsos-all:before, +.fi-torsos-female-male:before, +.fi-torsos-male-female:before, +.fi-torsos:before, +.fi-trash:before, +.fi-trees:before, +.fi-trophy:before, +.fi-underline:before, +.fi-universal-access:before, +.fi-unlink:before, +.fi-unlock:before, +.fi-upload-cloud:before, +.fi-upload:before, +.fi-usb:before, +.fi-video:before, +.fi-volume-none:before, +.fi-volume-strike:before, +.fi-volume:before, +.fi-web:before, +.fi-wheelchair:before, +.fi-widget:before, +.fi-wrench:before, +.fi-x-circle:before, +.fi-x:before, +.fi-yen:before, +.fi-zoom-in:before, +.fi-zoom-out:before { + font-family: "foundation-icons"; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + display: inline-block; + text-decoration: inherit; +} + +.fi-address-book:before { content: "\f100"; } +.fi-alert:before { content: "\f101"; } +.fi-align-center:before { content: "\f102"; } +.fi-align-justify:before { content: "\f103"; } +.fi-align-left:before { content: "\f104"; } +.fi-align-right:before { content: "\f105"; } +.fi-anchor:before { content: "\f106"; } +.fi-annotate:before { content: "\f107"; } +.fi-archive:before { content: "\f108"; } +.fi-arrow-down:before { content: "\f109"; } +.fi-arrow-left:before { content: "\f10a"; } +.fi-arrow-right:before { content: "\f10b"; } +.fi-arrow-up:before { content: "\f10c"; } +.fi-arrows-compress:before { content: "\f10d"; } +.fi-arrows-expand:before { content: "\f10e"; } +.fi-arrows-in:before { content: "\f10f"; } +.fi-arrows-out:before { content: "\f110"; } +.fi-asl:before { content: "\f111"; } +.fi-asterisk:before { content: "\f112"; } +.fi-at-sign:before { content: "\f113"; } +.fi-background-color:before { content: "\f114"; } +.fi-battery-empty:before { content: "\f115"; } +.fi-battery-full:before { content: "\f116"; } +.fi-battery-half:before { content: "\f117"; } +.fi-bitcoin-circle:before { content: "\f118"; } +.fi-bitcoin:before { content: "\f119"; } +.fi-blind:before { content: "\f11a"; } +.fi-bluetooth:before { content: "\f11b"; } +.fi-bold:before { content: "\f11c"; } +.fi-book-bookmark:before { content: "\f11d"; } +.fi-book:before { content: "\f11e"; } +.fi-bookmark:before { content: "\f11f"; } +.fi-braille:before { content: "\f120"; } +.fi-burst-new:before { content: "\f121"; } +.fi-burst-sale:before { content: "\f122"; } +.fi-burst:before { content: "\f123"; } +.fi-calendar:before { content: "\f124"; } +.fi-camera:before { content: "\f125"; } +.fi-check:before { content: "\f126"; } +.fi-checkbox:before { content: "\f127"; } +.fi-clipboard-notes:before { content: "\f128"; } +.fi-clipboard-pencil:before { content: "\f129"; } +.fi-clipboard:before { content: "\f12a"; } +.fi-clock:before { content: "\f12b"; } +.fi-closed-caption:before { content: "\f12c"; } +.fi-cloud:before { content: "\f12d"; } +.fi-comment-minus:before { content: "\f12e"; } +.fi-comment-quotes:before { content: "\f12f"; } +.fi-comment-video:before { content: "\f130"; } +.fi-comment:before { content: "\f131"; } +.fi-comments:before { content: "\f132"; } +.fi-compass:before { content: "\f133"; } +.fi-contrast:before { content: "\f134"; } +.fi-credit-card:before { content: "\f135"; } +.fi-crop:before { content: "\f136"; } +.fi-crown:before { content: "\f137"; } +.fi-css3:before { content: "\f138"; } +.fi-database:before { content: "\f139"; } +.fi-die-five:before { content: "\f13a"; } +.fi-die-four:before { content: "\f13b"; } +.fi-die-one:before { content: "\f13c"; } +.fi-die-six:before { content: "\f13d"; } +.fi-die-three:before { content: "\f13e"; } +.fi-die-two:before { content: "\f13f"; } +.fi-dislike:before { content: "\f140"; } +.fi-dollar-bill:before { content: "\f141"; } +.fi-dollar:before { content: "\f142"; } +.fi-download:before { content: "\f143"; } +.fi-eject:before { content: "\f144"; } +.fi-elevator:before { content: "\f145"; } +.fi-euro:before { content: "\f146"; } +.fi-eye:before { content: "\f147"; } +.fi-fast-forward:before { content: "\f148"; } +.fi-female-symbol:before { content: "\f149"; } +.fi-female:before { content: "\f14a"; } +.fi-filter:before { content: "\f14b"; } +.fi-first-aid:before { content: "\f14c"; } +.fi-flag:before { content: "\f14d"; } +.fi-folder-add:before { content: "\f14e"; } +.fi-folder-lock:before { content: "\f14f"; } +.fi-folder:before { content: "\f150"; } +.fi-foot:before { content: "\f151"; } +.fi-foundation:before { content: "\f152"; } +.fi-graph-bar:before { content: "\f153"; } +.fi-graph-horizontal:before { content: "\f154"; } +.fi-graph-pie:before { content: "\f155"; } +.fi-graph-trend:before { content: "\f156"; } +.fi-guide-dog:before { content: "\f157"; } +.fi-hearing-aid:before { content: "\f158"; } +.fi-heart:before { content: "\f159"; } +.fi-home:before { content: "\f15a"; } +.fi-html5:before { content: "\f15b"; } +.fi-indent-less:before { content: "\f15c"; } +.fi-indent-more:before { content: "\f15d"; } +.fi-info:before { content: "\f15e"; } +.fi-italic:before { content: "\f15f"; } +.fi-key:before { content: "\f160"; } +.fi-laptop:before { content: "\f161"; } +.fi-layout:before { content: "\f162"; } +.fi-lightbulb:before { content: "\f163"; } +.fi-like:before { content: "\f164"; } +.fi-link:before { content: "\f165"; } +.fi-list-bullet:before { content: "\f166"; } +.fi-list-number:before { content: "\f167"; } +.fi-list-thumbnails:before { content: "\f168"; } +.fi-list:before { content: "\f169"; } +.fi-lock:before { content: "\f16a"; } +.fi-loop:before { content: "\f16b"; } +.fi-magnifying-glass:before { content: "\f16c"; } +.fi-mail:before { content: "\f16d"; } +.fi-male-female:before { content: "\f16e"; } +.fi-male-symbol:before { content: "\f16f"; } +.fi-male:before { content: "\f170"; } +.fi-map:before { content: "\f171"; } +.fi-marker:before { content: "\f172"; } +.fi-megaphone:before { content: "\f173"; } +.fi-microphone:before { content: "\f174"; } +.fi-minus-circle:before { content: "\f175"; } +.fi-minus:before { content: "\f176"; } +.fi-mobile-signal:before { content: "\f177"; } +.fi-mobile:before { content: "\f178"; } +.fi-monitor:before { content: "\f179"; } +.fi-mountains:before { content: "\f17a"; } +.fi-music:before { content: "\f17b"; } +.fi-next:before { content: "\f17c"; } +.fi-no-dogs:before { content: "\f17d"; } +.fi-no-smoking:before { content: "\f17e"; } +.fi-page-add:before { content: "\f17f"; } +.fi-page-copy:before { content: "\f180"; } +.fi-page-csv:before { content: "\f181"; } +.fi-page-delete:before { content: "\f182"; } +.fi-page-doc:before { content: "\f183"; } +.fi-page-edit:before { content: "\f184"; } +.fi-page-export-csv:before { content: "\f185"; } +.fi-page-export-doc:before { content: "\f186"; } +.fi-page-export-pdf:before { content: "\f187"; } +.fi-page-export:before { content: "\f188"; } +.fi-page-filled:before { content: "\f189"; } +.fi-page-multiple:before { content: "\f18a"; } +.fi-page-pdf:before { content: "\f18b"; } +.fi-page-remove:before { content: "\f18c"; } +.fi-page-search:before { content: "\f18d"; } +.fi-page:before { content: "\f18e"; } +.fi-paint-bucket:before { content: "\f18f"; } +.fi-paperclip:before { content: "\f190"; } +.fi-pause:before { content: "\f191"; } +.fi-paw:before { content: "\f192"; } +.fi-paypal:before { content: "\f193"; } +.fi-pencil:before { content: "\f194"; } +.fi-photo:before { content: "\f195"; } +.fi-play-circle:before { content: "\f196"; } +.fi-play-video:before { content: "\f197"; } +.fi-play:before { content: "\f198"; } +.fi-plus:before { content: "\f199"; } +.fi-pound:before { content: "\f19a"; } +.fi-power:before { content: "\f19b"; } +.fi-previous:before { content: "\f19c"; } +.fi-price-tag:before { content: "\f19d"; } +.fi-pricetag-multiple:before { content: "\f19e"; } +.fi-print:before { content: "\f19f"; } +.fi-prohibited:before { content: "\f1a0"; } +.fi-projection-screen:before { content: "\f1a1"; } +.fi-puzzle:before { content: "\f1a2"; } +.fi-quote:before { content: "\f1a3"; } +.fi-record:before { content: "\f1a4"; } +.fi-refresh:before { content: "\f1a5"; } +.fi-results-demographics:before { content: "\f1a6"; } +.fi-results:before { content: "\f1a7"; } +.fi-rewind-ten:before { content: "\f1a8"; } +.fi-rewind:before { content: "\f1a9"; } +.fi-rss:before { content: "\f1aa"; } +.fi-safety-cone:before { content: "\f1ab"; } +.fi-save:before { content: "\f1ac"; } +.fi-share:before { content: "\f1ad"; } +.fi-sheriff-badge:before { content: "\f1ae"; } +.fi-shield:before { content: "\f1af"; } +.fi-shopping-bag:before { content: "\f1b0"; } +.fi-shopping-cart:before { content: "\f1b1"; } +.fi-shuffle:before { content: "\f1b2"; } +.fi-skull:before { content: "\f1b3"; } +.fi-social-500px:before { content: "\f1b4"; } +.fi-social-adobe:before { content: "\f1b5"; } +.fi-social-amazon:before { content: "\f1b6"; } +.fi-social-android:before { content: "\f1b7"; } +.fi-social-apple:before { content: "\f1b8"; } +.fi-social-behance:before { content: "\f1b9"; } +.fi-social-bing:before { content: "\f1ba"; } +.fi-social-blogger:before { content: "\f1bb"; } +.fi-social-delicious:before { content: "\f1bc"; } +.fi-social-designer-news:before { content: "\f1bd"; } +.fi-social-deviant-art:before { content: "\f1be"; } +.fi-social-digg:before { content: "\f1bf"; } +.fi-social-dribbble:before { content: "\f1c0"; } +.fi-social-drive:before { content: "\f1c1"; } +.fi-social-dropbox:before { content: "\f1c2"; } +.fi-social-evernote:before { content: "\f1c3"; } +.fi-social-facebook:before { content: "\f1c4"; } +.fi-social-flickr:before { content: "\f1c5"; } +.fi-social-forrst:before { content: "\f1c6"; } +.fi-social-foursquare:before { content: "\f1c7"; } +.fi-social-game-center:before { content: "\f1c8"; } +.fi-social-github:before { content: "\f1c9"; } +.fi-social-google-plus:before { content: "\f1ca"; } +.fi-social-hacker-news:before { content: "\f1cb"; } +.fi-social-hi5:before { content: "\f1cc"; } +.fi-social-instagram:before { content: "\f1cd"; } +.fi-social-joomla:before { content: "\f1ce"; } +.fi-social-lastfm:before { content: "\f1cf"; } +.fi-social-linkedin:before { content: "\f1d0"; } +.fi-social-medium:before { content: "\f1d1"; } +.fi-social-myspace:before { content: "\f1d2"; } +.fi-social-orkut:before { content: "\f1d3"; } +.fi-social-path:before { content: "\f1d4"; } +.fi-social-picasa:before { content: "\f1d5"; } +.fi-social-pinterest:before { content: "\f1d6"; } +.fi-social-rdio:before { content: "\f1d7"; } +.fi-social-reddit:before { content: "\f1d8"; } +.fi-social-skillshare:before { content: "\f1d9"; } +.fi-social-skype:before { content: "\f1da"; } +.fi-social-smashing-mag:before { content: "\f1db"; } +.fi-social-snapchat:before { content: "\f1dc"; } +.fi-social-spotify:before { content: "\f1dd"; } +.fi-social-squidoo:before { content: "\f1de"; } +.fi-social-stack-overflow:before { content: "\f1df"; } +.fi-social-steam:before { content: "\f1e0"; } +.fi-social-stumbleupon:before { content: "\f1e1"; } +.fi-social-treehouse:before { content: "\f1e2"; } +.fi-social-tumblr:before { content: "\f1e3"; } +.fi-social-twitter:before { content: "\f1e4"; } +.fi-social-vimeo:before { content: "\f1e5"; } +.fi-social-windows:before { content: "\f1e6"; } +.fi-social-xbox:before { content: "\f1e7"; } +.fi-social-yahoo:before { content: "\f1e8"; } +.fi-social-yelp:before { content: "\f1e9"; } +.fi-social-youtube:before { content: "\f1ea"; } +.fi-social-zerply:before { content: "\f1eb"; } +.fi-social-zurb:before { content: "\f1ec"; } +.fi-sound:before { content: "\f1ed"; } +.fi-star:before { content: "\f1ee"; } +.fi-stop:before { content: "\f1ef"; } +.fi-strikethrough:before { content: "\f1f0"; } +.fi-subscript:before { content: "\f1f1"; } +.fi-superscript:before { content: "\f1f2"; } +.fi-tablet-landscape:before { content: "\f1f3"; } +.fi-tablet-portrait:before { content: "\f1f4"; } +.fi-target-two:before { content: "\f1f5"; } +.fi-target:before { content: "\f1f6"; } +.fi-telephone-accessible:before { content: "\f1f7"; } +.fi-telephone:before { content: "\f1f8"; } +.fi-text-color:before { content: "\f1f9"; } +.fi-thumbnails:before { content: "\f1fa"; } +.fi-ticket:before { content: "\f1fb"; } +.fi-torso-business:before { content: "\f1fc"; } +.fi-torso-female:before { content: "\f1fd"; } +.fi-torso:before { content: "\f1fe"; } +.fi-torsos-all-female:before { content: "\f1ff"; } +.fi-torsos-all:before { content: "\f200"; } +.fi-torsos-female-male:before { content: "\f201"; } +.fi-torsos-male-female:before { content: "\f202"; } +.fi-torsos:before { content: "\f203"; } +.fi-trash:before { content: "\f204"; } +.fi-trees:before { content: "\f205"; } +.fi-trophy:before { content: "\f206"; } +.fi-underline:before { content: "\f207"; } +.fi-universal-access:before { content: "\f208"; } +.fi-unlink:before { content: "\f209"; } +.fi-unlock:before { content: "\f20a"; } +.fi-upload-cloud:before { content: "\f20b"; } +.fi-upload:before { content: "\f20c"; } +.fi-usb:before { content: "\f20d"; } +.fi-video:before { content: "\f20e"; } +.fi-volume-none:before { content: "\f20f"; } +.fi-volume-strike:before { content: "\f210"; } +.fi-volume:before { content: "\f211"; } +.fi-web:before { content: "\f212"; } +.fi-wheelchair:before { content: "\f213"; } +.fi-widget:before { content: "\f214"; } +.fi-wrench:before { content: "\f215"; } +.fi-x-circle:before { content: "\f216"; } +.fi-x:before { content: "\f217"; } +.fi-yen:before { content: "\f218"; } +.fi-zoom-in:before { content: "\f219"; } +.fi-zoom-out:before { content: "\f21a"; } diff --git a/sopds_web_backend/static/foundation-icons/foundation-icons.eot b/sopds_web_backend/static/foundation-icons/foundation-icons.eot new file mode 100644 index 0000000000000000000000000000000000000000..1746ad407fecf570ead54e216dc4bd7c79271206 Binary files /dev/null and b/sopds_web_backend/static/foundation-icons/foundation-icons.eot differ diff --git a/sopds_web_backend/static/foundation-icons/foundation-icons.svg b/sopds_web_backend/static/foundation-icons/foundation-icons.svg new file mode 100644 index 0000000000000000000000000000000000000000..4e014ff8907affbc8a44a9e7214bea9451350894 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/foundation-icons.svg @@ -0,0 +1,970 @@ + + + + + +Created by FontForge 20120731 at Fri Aug 23 09:25:55 2013 + By Jordan Humphreys +Created by Jordan Humphreys with FontForge 2.0 (http://fontforge.sf.net) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/foundation-icons.ttf b/sopds_web_backend/static/foundation-icons/foundation-icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6cce217ddc2efe3411dc9fa34e294e48e4cdf4f5 Binary files /dev/null and b/sopds_web_backend/static/foundation-icons/foundation-icons.ttf differ diff --git a/sopds_web_backend/static/foundation-icons/foundation-icons.woff b/sopds_web_backend/static/foundation-icons/foundation-icons.woff new file mode 100644 index 0000000000000000000000000000000000000000..e2cfe25dd392203f910d5deadd19beebe7e99984 Binary files /dev/null and b/sopds_web_backend/static/foundation-icons/foundation-icons.woff differ diff --git a/sopds_web_backend/static/foundation-icons/preview.html b/sopds_web_backend/static/foundation-icons/preview.html new file mode 100644 index 0000000000000000000000000000000000000000..cb439a38abef96a4d95e68b5e21adf9fd0517bb2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/preview.html @@ -0,0 +1,3798 @@ + + + + + Foundation Icons glyphs preview + + + + + + + + +
+

Foundation Icons contains 283 glyphs:

+ + +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+
+ +
+
+ 12141618212436486072 +
+
+ + +
+
+ +
+ + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-address-book.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-address-book.svg new file mode 100644 index 0000000000000000000000000000000000000000..0f72e2103aa99f2f6682ed7cde0242b796e9f495 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-address-book.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-alert.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-alert.svg new file mode 100644 index 0000000000000000000000000000000000000000..fffefe722a3c2330ec448ca2406deca2f8f71740 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-alert.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-align-center.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-align-center.svg new file mode 100644 index 0000000000000000000000000000000000000000..9534a4e2b7b5ff8508d4d627d8648393af234f76 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-align-center.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-align-justify.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-align-justify.svg new file mode 100644 index 0000000000000000000000000000000000000000..e5cc50cd575fd5720706ace8405c505a88472f3d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-align-justify.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-align-left.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-align-left.svg new file mode 100644 index 0000000000000000000000000000000000000000..d911ab3a3247868cdcc240b19fdc0602602be70e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-align-left.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-align-right.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-align-right.svg new file mode 100644 index 0000000000000000000000000000000000000000..0921087ffbb63eaf88aa8056f80004f6a98ed0f4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-align-right.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-anchor.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-anchor.svg new file mode 100644 index 0000000000000000000000000000000000000000..1f1ec22f745b9b0880292f5a5ee9fba61011f8ce --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-anchor.svg @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-annotate.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-annotate.svg new file mode 100644 index 0000000000000000000000000000000000000000..39b87fac59aad7c5a83c2bf78ca9199af9003018 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-annotate.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-archive.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-archive.svg new file mode 100644 index 0000000000000000000000000000000000000000..560d4a712adf099e454bdf4a7450716dc0b34d4a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-archive.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-down.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-down.svg new file mode 100644 index 0000000000000000000000000000000000000000..2ca99a83c42dcdf6e40f6153bff565ba9182790b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-down.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-left.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-left.svg new file mode 100644 index 0000000000000000000000000000000000000000..0d54f1bcfca3e6547bf39f0bdc4d8f1434101ae4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-left.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-right.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-right.svg new file mode 100644 index 0000000000000000000000000000000000000000..0eece6d64ed68def26f9d671579c5bbb42f5734e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-right.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-up.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-up.svg new file mode 100644 index 0000000000000000000000000000000000000000..c2c978899210d85b763e25ec40ef108e35784dd8 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrow-up.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-compress.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-compress.svg new file mode 100644 index 0000000000000000000000000000000000000000..d1ec83a783557c32b9b709888017b4ed20fbff53 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-compress.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-expand.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-expand.svg new file mode 100644 index 0000000000000000000000000000000000000000..14795a0a82f0ea058652ca706e9b05b739fd9586 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-expand.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-in.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-in.svg new file mode 100644 index 0000000000000000000000000000000000000000..08286329d27668c0a025a0e520b90cdd606b5f67 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-in.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-out.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-out.svg new file mode 100644 index 0000000000000000000000000000000000000000..df45691c25dbf74f418d3f52b77ef5c02e36f0ed --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-arrows-out.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-asl.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-asl.svg new file mode 100644 index 0000000000000000000000000000000000000000..fc1b4a5632376158b22c1218ad064e2d4247b478 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-asl.svg @@ -0,0 +1,52 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-asterisk.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-asterisk.svg new file mode 100644 index 0000000000000000000000000000000000000000..6f6819d0cf0c2f9cfb340717e514eaca0a5fb41e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-asterisk.svg @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-at-sign.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-at-sign.svg new file mode 100644 index 0000000000000000000000000000000000000000..38253a908706e37a29d050f9fd2944e8c871d59a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-at-sign.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-background-color.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-background-color.svg new file mode 100644 index 0000000000000000000000000000000000000000..65843a7c6e9e7fc20db59600d9f9cddf9e309e69 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-background-color.svg @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-battery-empty.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-battery-empty.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ef5734b7f5b225e333888277ac308cc4691db4c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-battery-empty.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-battery-full.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-battery-full.svg new file mode 100644 index 0000000000000000000000000000000000000000..6c333447d9a0faeaa5da55233d92a316832dc9cc --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-battery-full.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-battery-half.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-battery-half.svg new file mode 100644 index 0000000000000000000000000000000000000000..efd7f798cd3aeea4b6a8375f2bd3510699d7a9e8 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-battery-half.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-bitcoin-circle.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-bitcoin-circle.svg new file mode 100644 index 0000000000000000000000000000000000000000..22a62a95874da3643c73276f0ffcadee09d386f3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-bitcoin-circle.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-bitcoin.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-bitcoin.svg new file mode 100644 index 0000000000000000000000000000000000000000..dd5e9d813772dc068bb215b8fd8770791fb6329f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-bitcoin.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-blind.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-blind.svg new file mode 100644 index 0000000000000000000000000000000000000000..cde5d3f30219558c9054ce33e251ab95c06bd7d4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-blind.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-bluetooth.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-bluetooth.svg new file mode 100644 index 0000000000000000000000000000000000000000..3c203536cec4a6ae2c7493313164610dc94f1f96 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-bluetooth.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-bold.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-bold.svg new file mode 100644 index 0000000000000000000000000000000000000000..4acb923e75c338eb97102e1c9edd084a67591bd9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-bold.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-book-bookmark.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-book-bookmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..39102a5085e4c6747ae267355a1e4957219b541b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-book-bookmark.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-book.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-book.svg new file mode 100644 index 0000000000000000000000000000000000000000..abdedebd767c4af5a501fa5b0ba77623883834da --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-book.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-bookmark.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-bookmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..1248622b835812695091f8f31a29da8ac7d247d5 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-bookmark.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-braille.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-braille.svg new file mode 100644 index 0000000000000000000000000000000000000000..30fc6cb5141f06c4af5c76b24849097afdd4b7d0 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-braille.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-burst-new.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-burst-new.svg new file mode 100644 index 0000000000000000000000000000000000000000..c36ea1bbe81308d1aaa4159111a414fce1e3910e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-burst-new.svg @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-burst-sale.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-burst-sale.svg new file mode 100644 index 0000000000000000000000000000000000000000..d9d71e3f0bf9a366105636ad8a8cb4b9209713fd --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-burst-sale.svg @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-burst.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-burst.svg new file mode 100644 index 0000000000000000000000000000000000000000..7360ecb0abcd59c4dedf2d576b3d9b6e43e1c9f9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-burst.svg @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-calendar.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-calendar.svg new file mode 100644 index 0000000000000000000000000000000000000000..e3ace20f69d73bf9ad7fa71ac88292cefd42281c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-calendar.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-camera.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-camera.svg new file mode 100644 index 0000000000000000000000000000000000000000..06e127462b3d0162a796f32145203eae51a88c99 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-camera.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-check.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-check.svg new file mode 100644 index 0000000000000000000000000000000000000000..2cb7716ad802d53cb2b564cf03704cc8902c085b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-check.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-checkbox.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-checkbox.svg new file mode 100644 index 0000000000000000000000000000000000000000..2be4e6241a55cd7de39edd2fddccb401dd531ffc --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-checkbox.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard-notes.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard-notes.svg new file mode 100644 index 0000000000000000000000000000000000000000..c1ac67d262a82109dc95ffa662ba728211584c7a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard-notes.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard-pencil.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard-pencil.svg new file mode 100644 index 0000000000000000000000000000000000000000..f3d7cd6f9ae648684fe963febc64f6c845b22dd4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard-pencil.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard.svg new file mode 100644 index 0000000000000000000000000000000000000000..cc49bfd7fe1456ef91193690dd025f4b30ec1b9a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-clipboard.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-clock.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-clock.svg new file mode 100644 index 0000000000000000000000000000000000000000..546747be227e4ea5e81500b35ac4cbc0ad186b31 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-clock.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-closed-caption.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-closed-caption.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd086d1087e27f17f61688efb9887e08a502250b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-closed-caption.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-cloud.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-cloud.svg new file mode 100644 index 0000000000000000000000000000000000000000..505a68345230527aac2052304e4d3f92317c205f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-cloud.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-comment-minus.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-comment-minus.svg new file mode 100644 index 0000000000000000000000000000000000000000..3aae251d9cc684c800fd0ad9a549b0b1e1608bc6 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-comment-minus.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-comment-quotes.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-comment-quotes.svg new file mode 100644 index 0000000000000000000000000000000000000000..bb004535c4abe499848228aa84d2c082373310d8 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-comment-quotes.svg @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-comment-video.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-comment-video.svg new file mode 100644 index 0000000000000000000000000000000000000000..93f7403e4b58eec5109aea3b35c3ba17fae0733c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-comment-video.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-comment.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-comment.svg new file mode 100644 index 0000000000000000000000000000000000000000..22de7569dac01c4537de55d53bc0bce1f68d4f3f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-comment.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-comments.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-comments.svg new file mode 100644 index 0000000000000000000000000000000000000000..8b0493a5848cd9fdcc595a3c143004ad2081062c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-comments.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-compass.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-compass.svg new file mode 100644 index 0000000000000000000000000000000000000000..a18687eedc2304c8c99effe1f67190df03a7038c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-compass.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-contrast.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-contrast.svg new file mode 100644 index 0000000000000000000000000000000000000000..f3b775384dc27892a12c48dc0081275aa6f09436 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-contrast.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-credit-card.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-credit-card.svg new file mode 100644 index 0000000000000000000000000000000000000000..4b9eb30dab0cc43b8efac45ec6897be8536be79f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-credit-card.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-crop.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-crop.svg new file mode 100644 index 0000000000000000000000000000000000000000..fc9871133445f578d18164968728851d4907efd3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-crop.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-crown.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-crown.svg new file mode 100644 index 0000000000000000000000000000000000000000..cc6c7eccbe14e1d33eaedfdce58dd7a6af4a0991 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-crown.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-css3.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-css3.svg new file mode 100644 index 0000000000000000000000000000000000000000..2cf61bb58dcd5dec655ccdd0ac5995b34c559676 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-css3.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-database.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-database.svg new file mode 100644 index 0000000000000000000000000000000000000000..37f5f612e10edb5574ba1d701c88e33887a6ea74 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-database.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-die-five.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-die-five.svg new file mode 100644 index 0000000000000000000000000000000000000000..ab5e8fdc2a54d41589b44d99bb55103e120bd932 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-die-five.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-die-four.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-die-four.svg new file mode 100644 index 0000000000000000000000000000000000000000..5a0505ed0df274ed7c460bbb9730cbdc4d1d7515 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-die-four.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-die-one.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-die-one.svg new file mode 100644 index 0000000000000000000000000000000000000000..e18fab571e1268605251ec3900914beb947bb509 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-die-one.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-die-six.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-die-six.svg new file mode 100644 index 0000000000000000000000000000000000000000..bddb1fced6114651cb485da36458b7e679be63b7 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-die-six.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-die-three.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-die-three.svg new file mode 100644 index 0000000000000000000000000000000000000000..609e5b23538df297b4a686da1090d6a48257fc1b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-die-three.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-die-two.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-die-two.svg new file mode 100644 index 0000000000000000000000000000000000000000..62ea9eff2db3efdbec309b59b618ec09a03c661b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-die-two.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-dislike.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-dislike.svg new file mode 100644 index 0000000000000000000000000000000000000000..eca4f08b6fab291dc42dd09195581211325ad25a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-dislike.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-dollar-bill.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-dollar-bill.svg new file mode 100644 index 0000000000000000000000000000000000000000..7720d227fa42ba6801d9adb0b91db7fffd765d99 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-dollar-bill.svg @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-dollar.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-dollar.svg new file mode 100644 index 0000000000000000000000000000000000000000..176140d6d4b74b5eb0d23e8d09fdac60b40273d5 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-dollar.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-download.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-download.svg new file mode 100644 index 0000000000000000000000000000000000000000..563847ec20ffcd0a5b982a6edf3665f1500f4287 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-download.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-eject.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-eject.svg new file mode 100644 index 0000000000000000000000000000000000000000..d3634b04a5325ae4c8f9856e43f9fe4eda626137 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-eject.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-elevator.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-elevator.svg new file mode 100644 index 0000000000000000000000000000000000000000..0b21567741e477ef53a3811717bb1c861bfebdee --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-elevator.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-euro.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-euro.svg new file mode 100644 index 0000000000000000000000000000000000000000..7bb680d2703bd0555aa2b43748753126cd471671 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-euro.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-eye.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-eye.svg new file mode 100644 index 0000000000000000000000000000000000000000..ad360209e18277d25618a6e1fbf68c34ef67f9f8 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-eye.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-fast-forward.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-fast-forward.svg new file mode 100644 index 0000000000000000000000000000000000000000..b54cf184dd666380e7ede825c42d8e7ad4764cfa --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-fast-forward.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-female-symbol.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-female-symbol.svg new file mode 100644 index 0000000000000000000000000000000000000000..0ee8d0e70f93e4a5f11bfa7fdf719f7b8df58820 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-female-symbol.svg @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-female.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-female.svg new file mode 100644 index 0000000000000000000000000000000000000000..cf18fa3e757509bb0dad0e98e884722c0bf8e412 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-female.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-filter.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-filter.svg new file mode 100644 index 0000000000000000000000000000000000000000..8cb75a0edbba57ce66affed790a920133a66187a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-filter.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-first-aid.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-first-aid.svg new file mode 100644 index 0000000000000000000000000000000000000000..a10b0e09f049c61350e264df4d78662b6d1efe46 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-first-aid.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-flag.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-flag.svg new file mode 100644 index 0000000000000000000000000000000000000000..cdf74f827045f5aadfac21319b713613b385c96a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-flag.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-folder-add.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-folder-add.svg new file mode 100644 index 0000000000000000000000000000000000000000..7dd2d81da3c637454054e376649618784161b03f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-folder-add.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-folder-lock.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-folder-lock.svg new file mode 100644 index 0000000000000000000000000000000000000000..53b7745b69977114bec5264de03643996fea6491 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-folder-lock.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-folder.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-folder.svg new file mode 100644 index 0000000000000000000000000000000000000000..4c70436e8e8058d82093b1216b1b26edc5aef2d9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-folder.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-foot.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-foot.svg new file mode 100644 index 0000000000000000000000000000000000000000..d02f1abdc2d9336986beb133db181b1af18ac536 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-foot.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-foundation.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-foundation.svg new file mode 100644 index 0000000000000000000000000000000000000000..250140d5ac4a94da94413d2e6e3f68507fad961c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-foundation.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-graph-bar.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-bar.svg new file mode 100644 index 0000000000000000000000000000000000000000..c195dfb7ad4638ef3ff68f5bd7f1d0bc6b8c937f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-bar.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-graph-horizontal.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-horizontal.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ef147cd856229bbfbbedec176a52ff17b2e2086 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-horizontal.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-graph-pie.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-pie.svg new file mode 100644 index 0000000000000000000000000000000000000000..dd013dbf07d66e675b0858b5389dd806b7be553d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-pie.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-graph-trend.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-trend.svg new file mode 100644 index 0000000000000000000000000000000000000000..bdcf64875073b7ccfac67c62ce20cca0d3c16840 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-graph-trend.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-guide-dog.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-guide-dog.svg new file mode 100644 index 0000000000000000000000000000000000000000..2b3f0f98d629a391a098fb63f88c36119971e5c9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-guide-dog.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-hearing-aid.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-hearing-aid.svg new file mode 100644 index 0000000000000000000000000000000000000000..ec758cbf70eccdd5ad542e24df4be32e71ac089b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-hearing-aid.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-heart.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-heart.svg new file mode 100644 index 0000000000000000000000000000000000000000..264bdba1c312457126268cf31c7033d1050d7e6d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-heart.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-home.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-home.svg new file mode 100644 index 0000000000000000000000000000000000000000..6fe41cb33649f6a9e3b14a0a43fdc206c5a280fd --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-home.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-html5.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-html5.svg new file mode 100644 index 0000000000000000000000000000000000000000..8f3e74753940c3528c369b91678ad016a77cfa75 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-html5.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-indent-less.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-indent-less.svg new file mode 100644 index 0000000000000000000000000000000000000000..82bda2cc949f42ec172cf480932ba242c779c8fa --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-indent-less.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-indent-more.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-indent-more.svg new file mode 100644 index 0000000000000000000000000000000000000000..a0fb9480ca8bb1d14b2adfef55b13c7e653dc0c2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-indent-more.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-info.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-info.svg new file mode 100644 index 0000000000000000000000000000000000000000..ded5a99d12fa3abf78b9586fea4dc3b42c2ae619 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-info.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-italic.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-italic.svg new file mode 100644 index 0000000000000000000000000000000000000000..30a37bc27198fc8a4cae707b23ca5bca932b316c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-italic.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-key.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-key.svg new file mode 100644 index 0000000000000000000000000000000000000000..87ca7e11f0c9b05f22652495d14a53364679fd14 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-key.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-laptop.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-laptop.svg new file mode 100644 index 0000000000000000000000000000000000000000..2fe3f00be72db881360d57e335525f5d03765e93 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-laptop.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-layout.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-layout.svg new file mode 100644 index 0000000000000000000000000000000000000000..39b99fb3eb2e3d618d594b512f26f040b8a11acf --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-layout.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-lightbulb.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-lightbulb.svg new file mode 100644 index 0000000000000000000000000000000000000000..9fbefa35f9d90c1856597a9c2ad226a7c92f3ebb --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-lightbulb.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-like.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-like.svg new file mode 100644 index 0000000000000000000000000000000000000000..d2b932a5788aed4b65dcac95e72c775eeb505a5b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-like.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-link.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-link.svg new file mode 100644 index 0000000000000000000000000000000000000000..2de6156b16e73950a43ca5630fb95a3d8024a7c7 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-link.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-list-bullet.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-list-bullet.svg new file mode 100644 index 0000000000000000000000000000000000000000..83ee6737943942d392025948ecf5026715107544 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-list-bullet.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-list-number.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-list-number.svg new file mode 100644 index 0000000000000000000000000000000000000000..d75c192f29c1f5960c22a7391b7796cd967db0cc --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-list-number.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-list-thumbnails.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-list-thumbnails.svg new file mode 100644 index 0000000000000000000000000000000000000000..204ac4cee4eb80d172dc13b8863f2ebbcf6a043b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-list-thumbnails.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-list.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-list.svg new file mode 100644 index 0000000000000000000000000000000000000000..dfb1a8439d965089309aeccafac664d19b055fc3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-list.svg @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-lock.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-lock.svg new file mode 100644 index 0000000000000000000000000000000000000000..ed09e6fc3d9d55078999dc285fcbec6001da47ed --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-lock.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-loop.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-loop.svg new file mode 100644 index 0000000000000000000000000000000000000000..b48f7fdd14a05272d8c272eb08a58c821c267a9e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-loop.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-magnifying-glass.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-magnifying-glass.svg new file mode 100644 index 0000000000000000000000000000000000000000..890e1ca0a9bc0bddd381035aa3ef8275361360ae --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-magnifying-glass.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-mail.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-mail.svg new file mode 100644 index 0000000000000000000000000000000000000000..46603c7eda0559bdf5b479d07c3801e86cd0de06 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-mail.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-male-female.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-male-female.svg new file mode 100644 index 0000000000000000000000000000000000000000..c2a8a65b398b79ba94b09ac86548d4bd123316fa --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-male-female.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-male-symbol.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-male-symbol.svg new file mode 100644 index 0000000000000000000000000000000000000000..288fb2f1a3efb49e914a2e3f717b0aac0401e96f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-male-symbol.svg @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-male.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-male.svg new file mode 100644 index 0000000000000000000000000000000000000000..c0aee01931a025cb66c4073c9196393bf92b44a9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-male.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-map.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-map.svg new file mode 100644 index 0000000000000000000000000000000000000000..b4c97d1af58f86e1439969ac49820d2444da6846 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-map.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-marker.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-marker.svg new file mode 100644 index 0000000000000000000000000000000000000000..56c731e2f63cbce17fb0e56be175a974136ca058 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-marker.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-megaphone.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-megaphone.svg new file mode 100644 index 0000000000000000000000000000000000000000..8da1135bae8820bc88500ab6e293892d531011f3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-megaphone.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-microphone.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-microphone.svg new file mode 100644 index 0000000000000000000000000000000000000000..435d5b8168b26ba48bb76648bbe6fdb93ff3943a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-microphone.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-minus-circle.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-minus-circle.svg new file mode 100644 index 0000000000000000000000000000000000000000..e2cbf228a533d860f688f3c6049fc68e18f9ecd3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-minus-circle.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-minus.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-minus.svg new file mode 100644 index 0000000000000000000000000000000000000000..838abb2a14cc9849117346af46d06aa6a7b63764 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-minus.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-mobile-signal.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-mobile-signal.svg new file mode 100644 index 0000000000000000000000000000000000000000..38e69c2baaf68f2004fe75ec746680f41025edce --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-mobile-signal.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-mobile.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-mobile.svg new file mode 100644 index 0000000000000000000000000000000000000000..bed069538d4b2c5fa47500e9524bee0c536cb2f2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-mobile.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-monitor.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-monitor.svg new file mode 100644 index 0000000000000000000000000000000000000000..f314b90744916ef620cee88a68fd332abb6af11e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-monitor.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-mountains.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-mountains.svg new file mode 100644 index 0000000000000000000000000000000000000000..1af190770472e4ce80dcf3076f9ce32ee85a26ca --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-mountains.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-music.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-music.svg new file mode 100644 index 0000000000000000000000000000000000000000..bc21def91f43297bfdcb3d1fc457cf0d36d14fa4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-music.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-next.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-next.svg new file mode 100644 index 0000000000000000000000000000000000000000..6740b67dba5932167984d05abefb607165c6ac44 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-next.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-no-dogs.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-no-dogs.svg new file mode 100644 index 0000000000000000000000000000000000000000..c1fa625aaacd4467d3af00385010480ef5d658e4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-no-dogs.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-no-smoking.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-no-smoking.svg new file mode 100644 index 0000000000000000000000000000000000000000..84a30d93aa2f21720ae3762e89d91a7b317405a1 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-no-smoking.svg @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-add.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-add.svg new file mode 100644 index 0000000000000000000000000000000000000000..6933f12baf5cedba8f95b80bbce5e81ae8442a43 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-add.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-copy.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-copy.svg new file mode 100644 index 0000000000000000000000000000000000000000..5fca2fc4a22d3c9559b540901fe1274b9c581acd --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-copy.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-csv.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-csv.svg new file mode 100644 index 0000000000000000000000000000000000000000..4d328db5b2f946d0d1724bd7dd4ef11906c1056f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-csv.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-delete.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-delete.svg new file mode 100644 index 0000000000000000000000000000000000000000..05d1887b2732c1dde05856eca8ae1e120497050a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-delete.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-doc.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-doc.svg new file mode 100644 index 0000000000000000000000000000000000000000..7af02d47193986fe4a0c1f930d9b16e3e0183529 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-doc.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-edit.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-edit.svg new file mode 100644 index 0000000000000000000000000000000000000000..a01917f6dc9b2377153cdbc0569c75ba35ac9d1e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-edit.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-csv.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-csv.svg new file mode 100644 index 0000000000000000000000000000000000000000..67e56968fca44959988c45b0751a4b7d336407d7 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-csv.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-doc.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-doc.svg new file mode 100644 index 0000000000000000000000000000000000000000..f1438fbafad5c698787d1f1a3904bb40ba2178b3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-doc.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-pdf.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-pdf.svg new file mode 100644 index 0000000000000000000000000000000000000000..42675b9df23302744c6e2a683c0839722db87548 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export-pdf.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-export.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export.svg new file mode 100644 index 0000000000000000000000000000000000000000..eb6a234e41004e9a505a68d1d198d510676637f6 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-export.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-filled.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-filled.svg new file mode 100644 index 0000000000000000000000000000000000000000..2a096dc08f76b0882f4dcc472be75fc0f55ede48 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-filled.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-multiple.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-multiple.svg new file mode 100644 index 0000000000000000000000000000000000000000..c6ec943f27d248be15d3b3ca927694e069a5a6fd --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-multiple.svg @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-pdf.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-pdf.svg new file mode 100644 index 0000000000000000000000000000000000000000..d895e90bbeb806e7acee4be044e88b19d340f6e3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-pdf.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-remove.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-remove.svg new file mode 100644 index 0000000000000000000000000000000000000000..5d480aa7e05c79de93c551e4f1eba56250aa68bb --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-remove.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page-search.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page-search.svg new file mode 100644 index 0000000000000000000000000000000000000000..bbe154e1dc8de7e4e03cc223a25dc9600e941ed2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page-search.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-page.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-page.svg new file mode 100644 index 0000000000000000000000000000000000000000..559d58e81bfa509750625bbf104444185a0b2ed2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-page.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-paint-bucket.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-paint-bucket.svg new file mode 100644 index 0000000000000000000000000000000000000000..2ee33567f4ce998c4d28fd3dfee2e20d42a1a605 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-paint-bucket.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-paperclip.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-paperclip.svg new file mode 100644 index 0000000000000000000000000000000000000000..9ee9b961beca3ab079b7a4e8e59818b1aa2176ad --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-paperclip.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-pause.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-pause.svg new file mode 100644 index 0000000000000000000000000000000000000000..73b54362a8492f878bfdb5757e78833714440ae2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-pause.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-paw.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-paw.svg new file mode 100644 index 0000000000000000000000000000000000000000..d7b9b729da8f8aa5081a5782a564a232a3eb8896 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-paw.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-paypal.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-paypal.svg new file mode 100644 index 0000000000000000000000000000000000000000..8af9c429f9ee038f87d6336ceda5becfcb365a8e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-paypal.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-pencil.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-pencil.svg new file mode 100644 index 0000000000000000000000000000000000000000..b64ea8631fe4fb646bdfefda55f745f78945b120 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-pencil.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-photo.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-photo.svg new file mode 100644 index 0000000000000000000000000000000000000000..284a7588e57607a8644909890e6f1f4a4f0f228f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-photo.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-play-circle.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-play-circle.svg new file mode 100644 index 0000000000000000000000000000000000000000..738a087807e17e60a8911d13e2bd53e2b2605199 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-play-circle.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-play-video.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-play-video.svg new file mode 100644 index 0000000000000000000000000000000000000000..143fc7c3c3979a4492640edc58e39b30602cd401 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-play-video.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-play.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-play.svg new file mode 100644 index 0000000000000000000000000000000000000000..b91672529a66b479b0712c25550c01d55f5d739e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-play.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-plus.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-plus.svg new file mode 100644 index 0000000000000000000000000000000000000000..4de31100d21423e932ff9f6ef29382e3c9dd5205 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-plus.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-pound.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-pound.svg new file mode 100644 index 0000000000000000000000000000000000000000..b116d4d2bebde54b1b5a1d9f447d91ea5debf004 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-pound.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-power.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-power.svg new file mode 100644 index 0000000000000000000000000000000000000000..b3073f06815139250ae67cd0192e88063118c593 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-power.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-previous.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-previous.svg new file mode 100644 index 0000000000000000000000000000000000000000..6b391a7469e0f6e73163166e632588cc6ac4523d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-previous.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-price-tag.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-price-tag.svg new file mode 100644 index 0000000000000000000000000000000000000000..1511b57934d3a661c567c78797748597559f029a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-price-tag.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-pricetag-multiple.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-pricetag-multiple.svg new file mode 100644 index 0000000000000000000000000000000000000000..01067a6be314f9108d8b18e6f368048915e3aaa4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-pricetag-multiple.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-print.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-print.svg new file mode 100644 index 0000000000000000000000000000000000000000..79ccd4913a0fcc37b4854355cf1a9445c3f08f45 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-print.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-prohibited.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-prohibited.svg new file mode 100644 index 0000000000000000000000000000000000000000..f1364f5e69dad749395f71cdab197da3a464a0c9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-prohibited.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-projection-screen.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-projection-screen.svg new file mode 100644 index 0000000000000000000000000000000000000000..5d1e421818090526a58b0f309dba64b467959778 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-projection-screen.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-puzzle.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-puzzle.svg new file mode 100644 index 0000000000000000000000000000000000000000..cfce1c0d24d2c3039af38cfe9d954183d761beb3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-puzzle.svg @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-quote.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-quote.svg new file mode 100644 index 0000000000000000000000000000000000000000..ad42018a62d245fa22d4b3b988c17ef0037cb86e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-quote.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-record.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-record.svg new file mode 100644 index 0000000000000000000000000000000000000000..a4f00569833acfecd220419aad32351ebff75040 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-record.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-refresh.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-refresh.svg new file mode 100644 index 0000000000000000000000000000000000000000..c519432b779be576fd6eadfad2b672622add1082 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-refresh.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-results-demographics.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-results-demographics.svg new file mode 100644 index 0000000000000000000000000000000000000000..cddbea782aed142dca5851c3b5461acc0aba67e6 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-results-demographics.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-results.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-results.svg new file mode 100644 index 0000000000000000000000000000000000000000..68e9908ebcec20790e83578640bb0e93de131856 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-results.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-rewind-ten.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-rewind-ten.svg new file mode 100644 index 0000000000000000000000000000000000000000..e710526ca19c5f150b8305ce4b35b85044b2353d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-rewind-ten.svg @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-rewind.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-rewind.svg new file mode 100644 index 0000000000000000000000000000000000000000..8385736bf6be808922b789f9447939da03d6c44a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-rewind.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-rss.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-rss.svg new file mode 100644 index 0000000000000000000000000000000000000000..51a675e758860d88dc76a3c4e78b67e28cf96af4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-rss.svg @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-safety-cone.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-safety-cone.svg new file mode 100644 index 0000000000000000000000000000000000000000..7b8af9b3352a4803f2f722ba7a394675da954867 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-safety-cone.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-save.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-save.svg new file mode 100644 index 0000000000000000000000000000000000000000..b2247a520c6d5c91998f1075919b873c84f98bb5 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-save.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-share.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-share.svg new file mode 100644 index 0000000000000000000000000000000000000000..a083a45096cffc5366f1a5c7a83bd1124a264c24 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-share.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-sheriff-badge.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-sheriff-badge.svg new file mode 100644 index 0000000000000000000000000000000000000000..46387b386bedbf64f55fdaad4f9d4389990faaca --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-sheriff-badge.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-shield.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-shield.svg new file mode 100644 index 0000000000000000000000000000000000000000..5874c2bb4ea6dc3c7c18b8593f07d32f9b1d46c3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-shield.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-shopping-bag.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-shopping-bag.svg new file mode 100644 index 0000000000000000000000000000000000000000..43126aa19e49a36829f3163125ddc2fc05f4b5db --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-shopping-bag.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-shopping-cart.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-shopping-cart.svg new file mode 100644 index 0000000000000000000000000000000000000000..d4af8d8bc802cbcaae89bd03a573791508814cf1 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-shopping-cart.svg @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-shuffle.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-shuffle.svg new file mode 100644 index 0000000000000000000000000000000000000000..9baf4f4b448fdb14211101bcd487c0964290ddbc --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-shuffle.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-skull.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-skull.svg new file mode 100644 index 0000000000000000000000000000000000000000..72061b7fcd15a31364828457422537ec7b172892 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-skull.svg @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-500px.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-500px.svg new file mode 100644 index 0000000000000000000000000000000000000000..baac418c8fa9a1b4768bb36ea3983bfe9a1a3b9e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-500px.svg @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-adobe.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-adobe.svg new file mode 100644 index 0000000000000000000000000000000000000000..1f70a5a6938914c6ddda74bacb4d76d441031c14 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-adobe.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-amazon.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-amazon.svg new file mode 100644 index 0000000000000000000000000000000000000000..ebf39ceb0f49be3dafb3d0531fb17d38fd700581 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-amazon.svg @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-android.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-android.svg new file mode 100644 index 0000000000000000000000000000000000000000..0c7e5f20c283739e411e037a6c66ec439345e3d1 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-android.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-apple.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-apple.svg new file mode 100644 index 0000000000000000000000000000000000000000..e79b3ee40f79f892e88fde9584b48a01c9cfedff --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-apple.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-behance.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-behance.svg new file mode 100644 index 0000000000000000000000000000000000000000..afb4e0185816543461437e00c2d20c8f2b0a9ef3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-behance.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-bing.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-bing.svg new file mode 100644 index 0000000000000000000000000000000000000000..8db71242c23664ed0458ca190f0bc74a23c81d2b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-bing.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-blogger.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-blogger.svg new file mode 100644 index 0000000000000000000000000000000000000000..834de1b2c3461fddb0892326aef5d139f3437e18 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-blogger.svg @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-delicious.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-delicious.svg new file mode 100644 index 0000000000000000000000000000000000000000..5da3dcbcb67e236b9c248096538ddf8c2df9fb67 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-delicious.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-designer-news.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-designer-news.svg new file mode 100644 index 0000000000000000000000000000000000000000..1871ebcb8144c8faff8a354a4bbda110b4bf1de0 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-designer-news.svg @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-deviant-art.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-deviant-art.svg new file mode 100644 index 0000000000000000000000000000000000000000..a2672b343db5c2994bc425fa9318cf7cb002e9d6 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-deviant-art.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-digg.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-digg.svg new file mode 100644 index 0000000000000000000000000000000000000000..7613993bbc56ffe5a26f60f6c403c29acfd475aa --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-digg.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-dribbble.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-dribbble.svg new file mode 100644 index 0000000000000000000000000000000000000000..158842734e1c6bff7adb68777a81519b573647c2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-dribbble.svg @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-drive.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-drive.svg new file mode 100644 index 0000000000000000000000000000000000000000..aadf6af65116efd717ad264fe967d06f13a4a0db --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-drive.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-dropbox.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-dropbox.svg new file mode 100644 index 0000000000000000000000000000000000000000..cbbdf8876cb32b3ada437f8ed56188c2066b23a9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-dropbox.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-evernote.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-evernote.svg new file mode 100644 index 0000000000000000000000000000000000000000..accb31c53939ff0b44ace6135f29f5327ca4382a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-evernote.svg @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-facebook.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-facebook.svg new file mode 100644 index 0000000000000000000000000000000000000000..cd70aee902298af3062053e5194d47d9111962d5 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-facebook.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-flickr.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-flickr.svg new file mode 100644 index 0000000000000000000000000000000000000000..93e27e8310166f6a3f30b601eb7fbbddac678c6c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-flickr.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-forrst.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-forrst.svg new file mode 100644 index 0000000000000000000000000000000000000000..7a9f9b68a36eef3d27e6ef5a926dd31c180ee850 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-forrst.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-foursquare.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-foursquare.svg new file mode 100644 index 0000000000000000000000000000000000000000..223fe3de346e727ff4ce05cb912b16d795434199 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-foursquare.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-game-center.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-game-center.svg new file mode 100644 index 0000000000000000000000000000000000000000..6498f4918d987cc2ac51402ec475bde348b59790 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-game-center.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-github.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-github.svg new file mode 100644 index 0000000000000000000000000000000000000000..9628d354329f5b3857dfd773d9345448d62dfe7f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-github.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-google-plus.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-google-plus.svg new file mode 100644 index 0000000000000000000000000000000000000000..586e6b93e618844b0747d4df3b33a85dc2336e3a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-google-plus.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-hacker-news.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-hacker-news.svg new file mode 100644 index 0000000000000000000000000000000000000000..bccea9ab00817694dbd0747a2306220a6b4c0d7f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-hacker-news.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-hi5.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-hi5.svg new file mode 100644 index 0000000000000000000000000000000000000000..7554b82d4657c755bc4c4f24d60f4f8dbe698f6d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-hi5.svg @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-instagram.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-instagram.svg new file mode 100644 index 0000000000000000000000000000000000000000..c806e9b0dac294acdcdfedacbbbf62f0f2f4232d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-instagram.svg @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-joomla.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-joomla.svg new file mode 100644 index 0000000000000000000000000000000000000000..189497a95e721fb7fd5bc7a1c119dd1cf1f60aa1 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-joomla.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-lastfm.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-lastfm.svg new file mode 100644 index 0000000000000000000000000000000000000000..d940db6daeb189f838919d8738f512450ceb4921 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-lastfm.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-linkedin.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-linkedin.svg new file mode 100644 index 0000000000000000000000000000000000000000..fdfec24cc60e84cb78889585704d1f33d19a9bab --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-linkedin.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-medium.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-medium.svg new file mode 100644 index 0000000000000000000000000000000000000000..0926027e21b75f812d450f7eaadddb60989d6279 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-medium.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-myspace.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-myspace.svg new file mode 100644 index 0000000000000000000000000000000000000000..4fe0544c6a445a6aa55700b796ba586ad1002123 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-myspace.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-orkut.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-orkut.svg new file mode 100644 index 0000000000000000000000000000000000000000..3f239279e4db697115face05210904167acfc8a9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-orkut.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-path.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-path.svg new file mode 100644 index 0000000000000000000000000000000000000000..e0ee2be53c923c1b3673f2b823b639e119c2aae0 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-path.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-picasa.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-picasa.svg new file mode 100644 index 0000000000000000000000000000000000000000..cefa7119a238b0585a32a6bf85850ed16e7036fa --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-picasa.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-pinterest.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-pinterest.svg new file mode 100644 index 0000000000000000000000000000000000000000..1f49e8ec4fb866dbdb3e88a7d1efcbc8f226b9d7 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-pinterest.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-rdio.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-rdio.svg new file mode 100644 index 0000000000000000000000000000000000000000..ff43cb0ef1b126799e7ef3bed3c0caf1ac6c3a3c --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-rdio.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-reddit.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-reddit.svg new file mode 100644 index 0000000000000000000000000000000000000000..efc393bd1f80b65a74a4f0bef2fed997d73ce835 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-reddit.svg @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-skillshare.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-skillshare.svg new file mode 100644 index 0000000000000000000000000000000000000000..b711a5803e2214420cfc712952b8bfb6b046fa17 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-skillshare.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-skype.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-skype.svg new file mode 100644 index 0000000000000000000000000000000000000000..46d1cf1e2d72e48090e7cf1e72b527b4cea766d7 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-skype.svg @@ -0,0 +1,26 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-smashing-mag.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-smashing-mag.svg new file mode 100644 index 0000000000000000000000000000000000000000..ca5a3f8ccb03d6cb8e70b93664674d17dde53e40 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-smashing-mag.svg @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-snapchat.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-snapchat.svg new file mode 100644 index 0000000000000000000000000000000000000000..95f87c543397613aeb7ad7ac8a5bfcebf647ed45 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-snapchat.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-spotify.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-spotify.svg new file mode 100644 index 0000000000000000000000000000000000000000..065576c92dafa6791307dd2805119e8c51aacf01 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-spotify.svg @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-squidoo.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-squidoo.svg new file mode 100644 index 0000000000000000000000000000000000000000..44fa41f5e939101b4ac080dc7c368ccbf3386d9e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-squidoo.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-stack-overflow.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-stack-overflow.svg new file mode 100644 index 0000000000000000000000000000000000000000..e5fe8326b34094a304c51656a049bfcd1ece39ff --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-stack-overflow.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-steam.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-steam.svg new file mode 100644 index 0000000000000000000000000000000000000000..16e67ad2cd7a1b589a0da8c02d470f1337b0eb88 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-steam.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-stumbleupon.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-stumbleupon.svg new file mode 100644 index 0000000000000000000000000000000000000000..98c6b9361ea98433ff268e7b9f67cb91d3339dad --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-stumbleupon.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-treehouse.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-treehouse.svg new file mode 100644 index 0000000000000000000000000000000000000000..fb7e90d1b5443c1da228bdec2757f2b8d5000172 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-treehouse.svg @@ -0,0 +1,24 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-tumblr.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-tumblr.svg new file mode 100644 index 0000000000000000000000000000000000000000..2ebc4eed80168f9082d1bbce00217fa903c36b33 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-tumblr.svg @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-twitter.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-twitter.svg new file mode 100644 index 0000000000000000000000000000000000000000..b3472240f06acd7ca1c5052a00adef37b5b28975 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-twitter.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-vimeo.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-vimeo.svg new file mode 100644 index 0000000000000000000000000000000000000000..f9ced414667b254e0dea8c2195e75f86a61d26ab --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-vimeo.svg @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-windows.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-windows.svg new file mode 100644 index 0000000000000000000000000000000000000000..57ae0afe74bd97bd6c295f8e8f621e67e4eca3b4 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-windows.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-xbox.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-xbox.svg new file mode 100644 index 0000000000000000000000000000000000000000..a245044c5449aca65e66c3ccae3e206ace09636f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-xbox.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-yahoo.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-yahoo.svg new file mode 100644 index 0000000000000000000000000000000000000000..42a42a9dde2ad9ff28fa4efaa3cb0adb3be828b1 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-yahoo.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-yelp.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-yelp.svg new file mode 100644 index 0000000000000000000000000000000000000000..db257e8433b63b54462da3799def556667c4fed6 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-yelp.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-youtube.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-youtube.svg new file mode 100644 index 0000000000000000000000000000000000000000..f488af559762870581a36cefa7bec21e7489a92e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-youtube.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-zerply.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-zerply.svg new file mode 100644 index 0000000000000000000000000000000000000000..2e98b4908c76fc5e33c73420d4af57bb0382d049 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-zerply.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-social-zurb.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-social-zurb.svg new file mode 100644 index 0000000000000000000000000000000000000000..644761007d7a46d4d1a1db9ac131cb0fffb3ca99 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-social-zurb.svg @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-sound.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-sound.svg new file mode 100644 index 0000000000000000000000000000000000000000..ce3fca29cb67b559bc68b03e5447277eb406a5e3 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-sound.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-star.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-star.svg new file mode 100644 index 0000000000000000000000000000000000000000..da9bc090fe577757df0913ff0254778ecf7c02bb --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-star.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-stop.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-stop.svg new file mode 100644 index 0000000000000000000000000000000000000000..666cd755a68c6d2312a66b7fda6240cbf045c7cb --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-stop.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-strikethrough.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-strikethrough.svg new file mode 100644 index 0000000000000000000000000000000000000000..dd473c9c24d26d47cefb56c9aa0e7b2cd2ae0f62 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-strikethrough.svg @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-subscript.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-subscript.svg new file mode 100644 index 0000000000000000000000000000000000000000..2e96aa2d5a9672d8690518f06dd3bb45f265310f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-subscript.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-superscript.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-superscript.svg new file mode 100644 index 0000000000000000000000000000000000000000..f4f0ba71ee88b2b0f96f1d7789863cc88329cc49 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-superscript.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-tablet-landscape.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-tablet-landscape.svg new file mode 100644 index 0000000000000000000000000000000000000000..4480d3e57484dfea18e56887ab1d3fa18901f5ba --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-tablet-landscape.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-tablet-portrait.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-tablet-portrait.svg new file mode 100644 index 0000000000000000000000000000000000000000..84881068766b3bb6039cdfe8609a342576a3b182 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-tablet-portrait.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-target-two.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-target-two.svg new file mode 100644 index 0000000000000000000000000000000000000000..15059c4b794c4a4951d4f184f3a3305994e69dcb --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-target-two.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-target.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-target.svg new file mode 100644 index 0000000000000000000000000000000000000000..b1a028924afdce956ba91de185e168766f83e56f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-target.svg @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-telephone-accessible.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-telephone-accessible.svg new file mode 100644 index 0000000000000000000000000000000000000000..30b2b7394b8d7b8089cc8345cce2269d1387f1a0 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-telephone-accessible.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-telephone.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-telephone.svg new file mode 100644 index 0000000000000000000000000000000000000000..828a894e73da52732dcd6a427cdf0d78a321b6fa --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-telephone.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-text-color.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-text-color.svg new file mode 100644 index 0000000000000000000000000000000000000000..5a73110b6bfd8d01a187734950906953bb9e5202 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-text-color.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-thumbnails.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-thumbnails.svg new file mode 100644 index 0000000000000000000000000000000000000000..b2107cfaae662d220297ede96b2c850485b0375f --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-thumbnails.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-ticket.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-ticket.svg new file mode 100644 index 0000000000000000000000000000000000000000..5f55c64bbf9c59b33d25e024eb5938f86da30c6d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-ticket.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torso-business.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torso-business.svg new file mode 100644 index 0000000000000000000000000000000000000000..27f09cf1e971f0e58b2a3b180ce87d21ea08041e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torso-business.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torso-female.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torso-female.svg new file mode 100644 index 0000000000000000000000000000000000000000..d51dfd4b25bf4764545e90c12c6c82680f260ab2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torso-female.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torso.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torso.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd640c3fba5c9c881a2f9dfe35d6243de0e9de50 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torso.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-all-female.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-all-female.svg new file mode 100644 index 0000000000000000000000000000000000000000..74d8e4694bd14f25a7157df7e09e8b0dc95c7d15 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-all-female.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-all.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-all.svg new file mode 100644 index 0000000000000000000000000000000000000000..7fd97f0da436dd1c9761d6f4047e6d5e3c0e2bca --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-all.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-female-male.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-female-male.svg new file mode 100644 index 0000000000000000000000000000000000000000..637e572ebf30c54c1300a0e2bfef362062e21b22 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-female-male.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-male-female.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-male-female.svg new file mode 100644 index 0000000000000000000000000000000000000000..2f67e0b9ca545847c86a1f75b9a3fa054f43cb12 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos-male-female.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-torsos.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos.svg new file mode 100644 index 0000000000000000000000000000000000000000..37873c61324f3dfaca6ebdc092cd10bebaf74259 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-torsos.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-trash.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-trash.svg new file mode 100644 index 0000000000000000000000000000000000000000..395582636bd842c260dcb3f3f57690d7762367c5 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-trash.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-trees.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-trees.svg new file mode 100644 index 0000000000000000000000000000000000000000..55bc86e2973d97be56eb44ec5a54229f6566875b --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-trees.svg @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-trophy.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-trophy.svg new file mode 100644 index 0000000000000000000000000000000000000000..722c1676bcef102023cde6ae9e8bb46ae2ad69b9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-trophy.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-underline.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-underline.svg new file mode 100644 index 0000000000000000000000000000000000000000..adb2fd9e522e86b870d9ae1982eef7135d692740 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-underline.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-universal-access.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-universal-access.svg new file mode 100644 index 0000000000000000000000000000000000000000..5c2dca0b918c320fc15129c4ecc1211fef44c373 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-universal-access.svg @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-unlink.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-unlink.svg new file mode 100644 index 0000000000000000000000000000000000000000..fbc785108b16ec378dbeece05f270355f7362553 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-unlink.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-unlock.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-unlock.svg new file mode 100644 index 0000000000000000000000000000000000000000..c94929d2ed59413845b3392e5dc46eb5c3933ef2 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-unlock.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-upload-cloud.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-upload-cloud.svg new file mode 100644 index 0000000000000000000000000000000000000000..cc2d1354f790103287fa1646927b34fb63ec9edd --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-upload-cloud.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-upload.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-upload.svg new file mode 100644 index 0000000000000000000000000000000000000000..0536c3f22b1ac4b240e94ea9e672052871a4cefb --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-upload.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-usb.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-usb.svg new file mode 100644 index 0000000000000000000000000000000000000000..5f25dd8ec1a4b7f9d4c7032dceea4462635ae2d6 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-usb.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-video.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-video.svg new file mode 100644 index 0000000000000000000000000000000000000000..2ba31d71f3d3ee40169795ac507fe66ca298327d --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-video.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-volume-none.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-volume-none.svg new file mode 100644 index 0000000000000000000000000000000000000000..220f83f0d372cef72286bd2938e5065b258570a0 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-volume-none.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-volume-strike.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-volume-strike.svg new file mode 100644 index 0000000000000000000000000000000000000000..6f182e6e585bdc6a74ccea5b00bffd153f825564 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-volume-strike.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-volume.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-volume.svg new file mode 100644 index 0000000000000000000000000000000000000000..e435d9643474ee99c46d2e187e6020e07273cb42 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-volume.svg @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-web.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-web.svg new file mode 100644 index 0000000000000000000000000000000000000000..c7a28198254190dd75ce621df1bdb7854108143e --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-web.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-wheelchair.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-wheelchair.svg new file mode 100644 index 0000000000000000000000000000000000000000..efecd71465e7c290184464ab24b3b9ae6d21da9a --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-wheelchair.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-widget.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-widget.svg new file mode 100644 index 0000000000000000000000000000000000000000..925967f8b0943c1b40854cbf3d25a4cddbffe987 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-widget.svg @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-wrench.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-wrench.svg new file mode 100644 index 0000000000000000000000000000000000000000..cd0bcfcaee16521853c9928637c61687e0fc4ab9 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-wrench.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-x-circle.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-x-circle.svg new file mode 100644 index 0000000000000000000000000000000000000000..c037c71e38574622740bf79d712d86b36ae39013 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-x-circle.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-x.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-x.svg new file mode 100644 index 0000000000000000000000000000000000000000..85398ba77a9280ba0810cd500835286dc00d7628 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-x.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-yen.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-yen.svg new file mode 100644 index 0000000000000000000000000000000000000000..feffe66499c44d454406106fc1d11209956f1e77 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-yen.svg @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-zoom-in.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-zoom-in.svg new file mode 100644 index 0000000000000000000000000000000000000000..6b4213dc6b8e647a7c804a5859188a8a788c7280 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-zoom-in.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/foundation-icons/svgs/fi-zoom-out.svg b/sopds_web_backend/static/foundation-icons/svgs/fi-zoom-out.svg new file mode 100644 index 0000000000000000000000000000000000000000..0c07df7e8d30ec8797d7a374d41c3e0ba727ed86 --- /dev/null +++ b/sopds_web_backend/static/foundation-icons/svgs/fi-zoom-out.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/sopds_web_backend/static/images/favicon.ico b/sopds_web_backend/static/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..606445c0f6c851036ce1f1420d20a02960405d14 Binary files /dev/null and b/sopds_web_backend/static/images/favicon.ico differ diff --git a/sopds_web_backend/static/images/folder.png b/sopds_web_backend/static/images/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..23bd0788676b3b8f52d54816f68627979a8d6626 Binary files /dev/null and b/sopds_web_backend/static/images/folder.png differ diff --git a/sopds_web_backend/static/images/sopds_icon-big.gif b/sopds_web_backend/static/images/sopds_icon-big.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f3413fe1a5148ec112b9ecb8d051323b733d965 Binary files /dev/null and b/sopds_web_backend/static/images/sopds_icon-big.gif differ diff --git a/sopds_web_backend/static/images/sopds_icon.gif b/sopds_web_backend/static/images/sopds_icon.gif new file mode 100644 index 0000000000000000000000000000000000000000..91841460f69931b79e346687c3f1add8a410e4cf Binary files /dev/null and b/sopds_web_backend/static/images/sopds_icon.gif differ diff --git a/sopds_web_backend/static/images/sopds_icon.jpg b/sopds_web_backend/static/images/sopds_icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..28fcf5672fe1f4fc4d1e8ad68f5ddeb74be88764 Binary files /dev/null and b/sopds_web_backend/static/images/sopds_icon.jpg differ diff --git a/sopds_web_backend/static/images/sopds_icon2.gif b/sopds_web_backend/static/images/sopds_icon2.gif new file mode 100644 index 0000000000000000000000000000000000000000..7368df5474d38b347a6ea5fa4549ff0a483556ae Binary files /dev/null and b/sopds_web_backend/static/images/sopds_icon2.gif differ diff --git a/sopds_web_backend/static/images/sopds_logo.gif b/sopds_web_backend/static/images/sopds_logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..17ab24980de87c85b39a0ad092dfe6643d1304c9 Binary files /dev/null and b/sopds_web_backend/static/images/sopds_logo.gif differ diff --git a/sopds_web_backend/static/images/text.png b/sopds_web_backend/static/images/text.png new file mode 100644 index 0000000000000000000000000000000000000000..2f2cb808a88573d9259e557c548a486fb58929c0 Binary files /dev/null and b/sopds_web_backend/static/images/text.png differ diff --git a/sopds_web_backend/static/images/zip.png b/sopds_web_backend/static/images/zip.png new file mode 100644 index 0000000000000000000000000000000000000000..58b719e3432bbe3af00643da807635aed0f2b3d8 Binary files /dev/null and b/sopds_web_backend/static/images/zip.png differ diff --git a/sopds_web_backend/static/js/sopds.js b/sopds_web_backend/static/js/sopds.js new file mode 100644 index 0000000000000000000000000000000000000000..5b80fd13519ee904237c42107d7098cfd6c88f59 --- /dev/null +++ b/sopds_web_backend/static/js/sopds.js @@ -0,0 +1 @@ +$(document).foundation() diff --git a/sopds_web_backend/static/js/vendor/foundation.js b/sopds_web_backend/static/js/vendor/foundation.js new file mode 100644 index 0000000000000000000000000000000000000000..0265fff893f55bdc47dda12535c52b92e0c2ee64 --- /dev/null +++ b/sopds_web_backend/static/js/vendor/foundation.js @@ -0,0 +1,9124 @@ +!function ($) { + + "use strict"; + + var FOUNDATION_VERSION = '6.2.4'; + + // Global Foundation object + // This is attached to the window, or used as a module for AMD/Browserify + var Foundation = { + version: FOUNDATION_VERSION, + + /** + * Stores initialized plugins. + */ + _plugins: {}, + + /** + * Stores generated unique ids for plugin instances + */ + _uuids: [], + + /** + * Returns a boolean for RTL support + */ + rtl: function () { + return $('html').attr('dir') === 'rtl'; + }, + /** + * Defines a Foundation plugin, adding it to the `Foundation` namespace and the list of plugins to initialize when reflowing. + * @param {Object} plugin - The constructor of the plugin. + */ + plugin: function (plugin, name) { + // Object key to use when adding to global Foundation object + // Examples: Foundation.Reveal, Foundation.OffCanvas + var className = name || functionName(plugin); + // Object key to use when storing the plugin, also used to create the identifying data attribute for the plugin + // Examples: data-reveal, data-off-canvas + var attrName = hyphenate(className); + + // Add to the Foundation object and the plugins list (for reflowing) + this._plugins[attrName] = this[className] = plugin; + }, + /** + * @function + * Populates the _uuids array with pointers to each individual plugin instance. + * Adds the `zfPlugin` data-attribute to programmatically created plugins to allow use of $(selector).foundation(method) calls. + * Also fires the initialization event for each plugin, consolidating repetitive code. + * @param {Object} plugin - an instance of a plugin, usually `this` in context. + * @param {String} name - the name of the plugin, passed as a camelCased string. + * @fires Plugin#init + */ + registerPlugin: function (plugin, name) { + var pluginName = name ? hyphenate(name) : functionName(plugin.constructor).toLowerCase(); + plugin.uuid = this.GetYoDigits(6, pluginName); + + if (!plugin.$element.attr('data-' + pluginName)) { + plugin.$element.attr('data-' + pluginName, plugin.uuid); + } + if (!plugin.$element.data('zfPlugin')) { + plugin.$element.data('zfPlugin', plugin); + } + /** + * Fires when the plugin has initialized. + * @event Plugin#init + */ + plugin.$element.trigger('init.zf.' + pluginName); + + this._uuids.push(plugin.uuid); + + return; + }, + /** + * @function + * Removes the plugins uuid from the _uuids array. + * Removes the zfPlugin data attribute, as well as the data-plugin-name attribute. + * Also fires the destroyed event for the plugin, consolidating repetitive code. + * @param {Object} plugin - an instance of a plugin, usually `this` in context. + * @fires Plugin#destroyed + */ + unregisterPlugin: function (plugin) { + var pluginName = hyphenate(functionName(plugin.$element.data('zfPlugin').constructor)); + + this._uuids.splice(this._uuids.indexOf(plugin.uuid), 1); + plugin.$element.removeAttr('data-' + pluginName).removeData('zfPlugin') + /** + * Fires when the plugin has been destroyed. + * @event Plugin#destroyed + */ + .trigger('destroyed.zf.' + pluginName); + for (var prop in plugin) { + plugin[prop] = null; //clean up script to prep for garbage collection. + } + return; + }, + + /** + * @function + * Causes one or more active plugins to re-initialize, resetting event listeners, recalculating positions, etc. + * @param {String} plugins - optional string of an individual plugin key, attained by calling `$(element).data('pluginName')`, or string of a plugin class i.e. `'dropdown'` + * @default If no argument is passed, reflow all currently active plugins. + */ + reInit: function (plugins) { + var isJQ = plugins instanceof $; + try { + if (isJQ) { + plugins.each(function () { + $(this).data('zfPlugin')._init(); + }); + } else { + var type = typeof plugins, + _this = this, + fns = { + 'object': function (plgs) { + plgs.forEach(function (p) { + p = hyphenate(p); + $('[data-' + p + ']').foundation('_init'); + }); + }, + 'string': function () { + plugins = hyphenate(plugins); + $('[data-' + plugins + ']').foundation('_init'); + }, + 'undefined': function () { + this['object'](Object.keys(_this._plugins)); + } + }; + fns[type](plugins); + } + } catch (err) { + console.error(err); + } finally { + return plugins; + } + }, + + /** + * returns a random base-36 uid with namespacing + * @function + * @param {Number} length - number of random base-36 digits desired. Increase for more random strings. + * @param {String} namespace - name of plugin to be incorporated in uid, optional. + * @default {String} '' - if no plugin name is provided, nothing is appended to the uid. + * @returns {String} - unique id + */ + GetYoDigits: function (length, namespace) { + length = length || 6; + return Math.round(Math.pow(36, length + 1) - Math.random() * Math.pow(36, length)).toString(36).slice(1) + (namespace ? '-' + namespace : ''); + }, + /** + * Initialize plugins on any elements within `elem` (and `elem` itself) that aren't already initialized. + * @param {Object} elem - jQuery object containing the element to check inside. Also checks the element itself, unless it's the `document` object. + * @param {String|Array} plugins - A list of plugins to initialize. Leave this out to initialize everything. + */ + reflow: function (elem, plugins) { + + // If plugins is undefined, just grab everything + if (typeof plugins === 'undefined') { + plugins = Object.keys(this._plugins); + } + // If plugins is a string, convert it to an array with one item + else if (typeof plugins === 'string') { + plugins = [plugins]; + } + + var _this = this; + + // Iterate through each plugin + $.each(plugins, function (i, name) { + // Get the current plugin + var plugin = _this._plugins[name]; + + // Localize the search to all elements inside elem, as well as elem itself, unless elem === document + var $elem = $(elem).find('[data-' + name + ']').addBack('[data-' + name + ']'); + + // For each plugin found, initialize it + $elem.each(function () { + var $el = $(this), + opts = {}; + // Don't double-dip on plugins + if ($el.data('zfPlugin')) { + console.warn("Tried to initialize " + name + " on an element that already has a Foundation plugin."); + return; + } + + if ($el.attr('data-options')) { + var thing = $el.attr('data-options').split(';').forEach(function (e, i) { + var opt = e.split(':').map(function (el) { + return el.trim(); + }); + if (opt[0]) opts[opt[0]] = parseValue(opt[1]); + }); + } + try { + $el.data('zfPlugin', new plugin($(this), opts)); + } catch (er) { + console.error(er); + } finally { + return; + } + }); + }); + }, + getFnName: functionName, + transitionend: function ($elem) { + var transitions = { + 'transition': 'transitionend', + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'otransitionend' + }; + var elem = document.createElement('div'), + end; + + for (var t in transitions) { + if (typeof elem.style[t] !== 'undefined') { + end = transitions[t]; + } + } + if (end) { + return end; + } else { + end = setTimeout(function () { + $elem.triggerHandler('transitionend', [$elem]); + }, 1); + return 'transitionend'; + } + } + }; + + Foundation.util = { + /** + * Function for applying a debounce effect to a function call. + * @function + * @param {Function} func - Function to be called at end of timeout. + * @param {Number} delay - Time in ms to delay the call of `func`. + * @returns function + */ + throttle: function (func, delay) { + var timer = null; + + return function () { + var context = this, + args = arguments; + + if (timer === null) { + timer = setTimeout(function () { + func.apply(context, args); + timer = null; + }, delay); + } + }; + } + }; + + // TODO: consider not making this a jQuery function + // TODO: need way to reflow vs. re-initialize + /** + * The Foundation jQuery method. + * @param {String|Array} method - An action to perform on the current jQuery object. + */ + var foundation = function (method) { + var type = typeof method, + $meta = $('meta.foundation-mq'), + $noJS = $('.no-js'); + + if (!$meta.length) { + $('').appendTo(document.head); + } + if ($noJS.length) { + $noJS.removeClass('no-js'); + } + + if (type === 'undefined') { + //needs to initialize the Foundation object, or an individual plugin. + Foundation.MediaQuery._init(); + Foundation.reflow(this); + } else if (type === 'string') { + //an individual method to invoke on a plugin or group of plugins + var args = Array.prototype.slice.call(arguments, 1); //collect all the arguments, if necessary + var plugClass = this.data('zfPlugin'); //determine the class of plugin + + if (plugClass !== undefined && plugClass[method] !== undefined) { + //make sure both the class and method exist + if (this.length === 1) { + //if there's only one, call it directly. + plugClass[method].apply(plugClass, args); + } else { + this.each(function (i, el) { + //otherwise loop through the jQuery collection and invoke the method on each + plugClass[method].apply($(el).data('zfPlugin'), args); + }); + } + } else { + //error for no class or no method + throw new ReferenceError("We're sorry, '" + method + "' is not an available method for " + (plugClass ? functionName(plugClass) : 'this element') + '.'); + } + } else { + //error for invalid argument type + throw new TypeError('We\'re sorry, ' + type + ' is not a valid parameter. You must use a string representing the method you wish to invoke.'); + } + return this; + }; + + window.Foundation = Foundation; + $.fn.foundation = foundation; + + // Polyfill for requestAnimationFrame + (function () { + if (!Date.now || !window.Date.now) window.Date.now = Date.now = function () { + return new Date().getTime(); + }; + + var vendors = ['webkit', 'moz']; + for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { + var vp = vendors[i]; + window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame']; + } + if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) { + var lastTime = 0; + window.requestAnimationFrame = function (callback) { + var now = Date.now(); + var nextTime = Math.max(lastTime + 16, now); + return setTimeout(function () { + callback(lastTime = nextTime); + }, nextTime - now); + }; + window.cancelAnimationFrame = clearTimeout; + } + /** + * Polyfill for performance.now, required by rAF + */ + if (!window.performance || !window.performance.now) { + window.performance = { + start: Date.now(), + now: function () { + return Date.now() - this.start; + } + }; + } + })(); + if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + if (this.prototype) { + // native functions don't have a prototype + fNOP.prototype = this.prototype; + } + fBound.prototype = new fNOP(); + + return fBound; + }; + } + // Polyfill to get the name of a function in IE9 + function functionName(fn) { + if (Function.prototype.name === undefined) { + var funcNameRegex = /function\s([^(]{1,})\(/; + var results = funcNameRegex.exec(fn.toString()); + return results && results.length > 1 ? results[1].trim() : ""; + } else if (fn.prototype === undefined) { + return fn.constructor.name; + } else { + return fn.prototype.constructor.name; + } + } + function parseValue(str) { + if (/true/.test(str)) return true;else if (/false/.test(str)) return false;else if (!isNaN(str * 1)) return parseFloat(str); + return str; + } + // Convert PascalCase to kebab-case + // Thank you: http://stackoverflow.com/a/8955580 + function hyphenate(str) { + return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); + } +}(jQuery); +'use strict'; + +!function ($) { + + Foundation.Box = { + ImNotTouchingYou: ImNotTouchingYou, + GetDimensions: GetDimensions, + GetOffsets: GetOffsets + }; + + /** + * Compares the dimensions of an element to a container and determines collision events with container. + * @function + * @param {jQuery} element - jQuery object to test for collisions. + * @param {jQuery} parent - jQuery object to use as bounding container. + * @param {Boolean} lrOnly - set to true to check left and right values only. + * @param {Boolean} tbOnly - set to true to check top and bottom values only. + * @default if no parent object passed, detects collisions with `window`. + * @returns {Boolean} - true if collision free, false if a collision in any direction. + */ + function ImNotTouchingYou(element, parent, lrOnly, tbOnly) { + var eleDims = GetDimensions(element), + top, + bottom, + left, + right; + + if (parent) { + var parDims = GetDimensions(parent); + + bottom = eleDims.offset.top + eleDims.height <= parDims.height + parDims.offset.top; + top = eleDims.offset.top >= parDims.offset.top; + left = eleDims.offset.left >= parDims.offset.left; + right = eleDims.offset.left + eleDims.width <= parDims.width + parDims.offset.left; + } else { + bottom = eleDims.offset.top + eleDims.height <= eleDims.windowDims.height + eleDims.windowDims.offset.top; + top = eleDims.offset.top >= eleDims.windowDims.offset.top; + left = eleDims.offset.left >= eleDims.windowDims.offset.left; + right = eleDims.offset.left + eleDims.width <= eleDims.windowDims.width; + } + + var allDirs = [bottom, top, left, right]; + + if (lrOnly) { + return left === right === true; + } + + if (tbOnly) { + return top === bottom === true; + } + + return allDirs.indexOf(false) === -1; + }; + + /** + * Uses native methods to return an object of dimension values. + * @function + * @param {jQuery || HTML} element - jQuery object or DOM element for which to get the dimensions. Can be any element other that document or window. + * @returns {Object} - nested object of integer pixel values + * TODO - if element is window, return only those values. + */ + function GetDimensions(elem, test) { + elem = elem.length ? elem[0] : elem; + + if (elem === window || elem === document) { + throw new Error("I'm sorry, Dave. I'm afraid I can't do that."); + } + + var rect = elem.getBoundingClientRect(), + parRect = elem.parentNode.getBoundingClientRect(), + winRect = document.body.getBoundingClientRect(), + winY = window.pageYOffset, + winX = window.pageXOffset; + + return { + width: rect.width, + height: rect.height, + offset: { + top: rect.top + winY, + left: rect.left + winX + }, + parentDims: { + width: parRect.width, + height: parRect.height, + offset: { + top: parRect.top + winY, + left: parRect.left + winX + } + }, + windowDims: { + width: winRect.width, + height: winRect.height, + offset: { + top: winY, + left: winX + } + } + }; + } + + /** + * Returns an object of top and left integer pixel values for dynamically rendered elements, + * such as: Tooltip, Reveal, and Dropdown + * @function + * @param {jQuery} element - jQuery object for the element being positioned. + * @param {jQuery} anchor - jQuery object for the element's anchor point. + * @param {String} position - a string relating to the desired position of the element, relative to it's anchor + * @param {Number} vOffset - integer pixel value of desired vertical separation between anchor and element. + * @param {Number} hOffset - integer pixel value of desired horizontal separation between anchor and element. + * @param {Boolean} isOverflow - if a collision event is detected, sets to true to default the element to full width - any desired offset. + * TODO alter/rewrite to work with `em` values as well/instead of pixels + */ + function GetOffsets(element, anchor, position, vOffset, hOffset, isOverflow) { + var $eleDims = GetDimensions(element), + $anchorDims = anchor ? GetDimensions(anchor) : null; + + switch (position) { + case 'top': + return { + left: Foundation.rtl() ? $anchorDims.offset.left - $eleDims.width + $anchorDims.width : $anchorDims.offset.left, + top: $anchorDims.offset.top - ($eleDims.height + vOffset) + }; + break; + case 'left': + return { + left: $anchorDims.offset.left - ($eleDims.width + hOffset), + top: $anchorDims.offset.top + }; + break; + case 'right': + return { + left: $anchorDims.offset.left + $anchorDims.width + hOffset, + top: $anchorDims.offset.top + }; + break; + case 'center top': + return { + left: $anchorDims.offset.left + $anchorDims.width / 2 - $eleDims.width / 2, + top: $anchorDims.offset.top - ($eleDims.height + vOffset) + }; + break; + case 'center bottom': + return { + left: isOverflow ? hOffset : $anchorDims.offset.left + $anchorDims.width / 2 - $eleDims.width / 2, + top: $anchorDims.offset.top + $anchorDims.height + vOffset + }; + break; + case 'center left': + return { + left: $anchorDims.offset.left - ($eleDims.width + hOffset), + top: $anchorDims.offset.top + $anchorDims.height / 2 - $eleDims.height / 2 + }; + break; + case 'center right': + return { + left: $anchorDims.offset.left + $anchorDims.width + hOffset + 1, + top: $anchorDims.offset.top + $anchorDims.height / 2 - $eleDims.height / 2 + }; + break; + case 'center': + return { + left: $eleDims.windowDims.offset.left + $eleDims.windowDims.width / 2 - $eleDims.width / 2, + top: $eleDims.windowDims.offset.top + $eleDims.windowDims.height / 2 - $eleDims.height / 2 + }; + break; + case 'reveal': + return { + left: ($eleDims.windowDims.width - $eleDims.width) / 2, + top: $eleDims.windowDims.offset.top + vOffset + }; + case 'reveal full': + return { + left: $eleDims.windowDims.offset.left, + top: $eleDims.windowDims.offset.top + }; + break; + case 'left bottom': + return { + left: $anchorDims.offset.left, + top: $anchorDims.offset.top + $anchorDims.height + }; + break; + case 'right bottom': + return { + left: $anchorDims.offset.left + $anchorDims.width + hOffset - $eleDims.width, + top: $anchorDims.offset.top + $anchorDims.height + }; + break; + default: + return { + left: Foundation.rtl() ? $anchorDims.offset.left - $eleDims.width + $anchorDims.width : $anchorDims.offset.left + hOffset, + top: $anchorDims.offset.top + $anchorDims.height + vOffset + }; + } + } +}(jQuery); +/******************************************* + * * + * This util was created by Marius Olbertz * + * Please thank Marius on GitHub /owlbertz * + * or the web http://www.mariusolbertz.de/ * + * * + ******************************************/ + +'use strict'; + +!function ($) { + + var keyCodes = { + 9: 'TAB', + 13: 'ENTER', + 27: 'ESCAPE', + 32: 'SPACE', + 37: 'ARROW_LEFT', + 38: 'ARROW_UP', + 39: 'ARROW_RIGHT', + 40: 'ARROW_DOWN' + }; + + var commands = {}; + + var Keyboard = { + keys: getKeyCodes(keyCodes), + + /** + * Parses the (keyboard) event and returns a String that represents its key + * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE + * @param {Event} event - the event generated by the event handler + * @return String key - String that represents the key pressed + */ + parseKey: function (event) { + var key = keyCodes[event.which || event.keyCode] || String.fromCharCode(event.which).toUpperCase(); + if (event.shiftKey) key = 'SHIFT_' + key; + if (event.ctrlKey) key = 'CTRL_' + key; + if (event.altKey) key = 'ALT_' + key; + return key; + }, + + + /** + * Handles the given (keyboard) event + * @param {Event} event - the event generated by the event handler + * @param {String} component - Foundation component's name, e.g. Slider or Reveal + * @param {Objects} functions - collection of functions that are to be executed + */ + handleKey: function (event, component, functions) { + var commandList = commands[component], + keyCode = this.parseKey(event), + cmds, + command, + fn; + + if (!commandList) return console.warn('Component not defined!'); + + if (typeof commandList.ltr === 'undefined') { + // this component does not differentiate between ltr and rtl + cmds = commandList; // use plain list + } else { + // merge ltr and rtl: if document is rtl, rtl overwrites ltr and vice versa + if (Foundation.rtl()) cmds = $.extend({}, commandList.ltr, commandList.rtl);else cmds = $.extend({}, commandList.rtl, commandList.ltr); + } + command = cmds[keyCode]; + + fn = functions[command]; + if (fn && typeof fn === 'function') { + // execute function if exists + var returnValue = fn.apply(); + if (functions.handled || typeof functions.handled === 'function') { + // execute function when event was handled + functions.handled(returnValue); + } + } else { + if (functions.unhandled || typeof functions.unhandled === 'function') { + // execute function when event was not handled + functions.unhandled(); + } + } + }, + + + /** + * Finds all focusable elements within the given `$element` + * @param {jQuery} $element - jQuery object to search within + * @return {jQuery} $focusable - all focusable elements within `$element` + */ + findFocusable: function ($element) { + return $element.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').filter(function () { + if (!$(this).is(':visible') || $(this).attr('tabindex') < 0) { + return false; + } //only have visible elements and those that have a tabindex greater or equal 0 + return true; + }); + }, + + + /** + * Returns the component name name + * @param {Object} component - Foundation component, e.g. Slider or Reveal + * @return String componentName + */ + + register: function (componentName, cmds) { + commands[componentName] = cmds; + } + }; + + /* + * Constants for easier comparing. + * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE + */ + function getKeyCodes(kcs) { + var k = {}; + for (var kc in kcs) { + k[kcs[kc]] = kcs[kc]; + }return k; + } + + Foundation.Keyboard = Keyboard; +}(jQuery); +'use strict'; + +!function ($) { + + // Default set of media queries + var defaultQueries = { + 'default': 'only screen', + landscape: 'only screen and (orientation: landscape)', + portrait: 'only screen and (orientation: portrait)', + retina: 'only screen and (-webkit-min-device-pixel-ratio: 2),' + 'only screen and (min--moz-device-pixel-ratio: 2),' + 'only screen and (-o-min-device-pixel-ratio: 2/1),' + 'only screen and (min-device-pixel-ratio: 2),' + 'only screen and (min-resolution: 192dpi),' + 'only screen and (min-resolution: 2dppx)' + }; + + var MediaQuery = { + queries: [], + + current: '', + + /** + * Initializes the media query helper, by extracting the breakpoint list from the CSS and activating the breakpoint watcher. + * @function + * @private + */ + _init: function () { + var self = this; + var extractedStyles = $('.foundation-mq').css('font-family'); + var namedQueries; + + namedQueries = parseStyleToObject(extractedStyles); + + for (var key in namedQueries) { + if (namedQueries.hasOwnProperty(key)) { + self.queries.push({ + name: key, + value: 'only screen and (min-width: ' + namedQueries[key] + ')' + }); + } + } + + this.current = this._getCurrentSize(); + + this._watcher(); + }, + + + /** + * Checks if the screen is at least as wide as a breakpoint. + * @function + * @param {String} size - Name of the breakpoint to check. + * @returns {Boolean} `true` if the breakpoint matches, `false` if it's smaller. + */ + atLeast: function (size) { + var query = this.get(size); + + if (query) { + return window.matchMedia(query).matches; + } + + return false; + }, + + + /** + * Gets the media query of a breakpoint. + * @function + * @param {String} size - Name of the breakpoint to get. + * @returns {String|null} - The media query of the breakpoint, or `null` if the breakpoint doesn't exist. + */ + get: function (size) { + for (var i in this.queries) { + if (this.queries.hasOwnProperty(i)) { + var query = this.queries[i]; + if (size === query.name) return query.value; + } + } + + return null; + }, + + + /** + * Gets the current breakpoint name by testing every breakpoint and returning the last one to match (the biggest one). + * @function + * @private + * @returns {String} Name of the current breakpoint. + */ + _getCurrentSize: function () { + var matched; + + for (var i = 0; i < this.queries.length; i++) { + var query = this.queries[i]; + + if (window.matchMedia(query.value).matches) { + matched = query; + } + } + + if (typeof matched === 'object') { + return matched.name; + } else { + return matched; + } + }, + + + /** + * Activates the breakpoint watcher, which fires an event on the window whenever the breakpoint changes. + * @function + * @private + */ + _watcher: function () { + var _this = this; + + $(window).on('resize.zf.mediaquery', function () { + var newSize = _this._getCurrentSize(), + currentSize = _this.current; + + if (newSize !== currentSize) { + // Change the current media query + _this.current = newSize; + + // Broadcast the media query change on the window + $(window).trigger('changed.zf.mediaquery', [newSize, currentSize]); + } + }); + } + }; + + Foundation.MediaQuery = MediaQuery; + + // matchMedia() polyfill - Test a CSS media type/query in JS. + // Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license + window.matchMedia || (window.matchMedia = function () { + 'use strict'; + + // For browsers that support matchMedium api such as IE 9 and webkit + + var styleMedia = window.styleMedia || window.media; + + // For those that don't support matchMedium + if (!styleMedia) { + var style = document.createElement('style'), + script = document.getElementsByTagName('script')[0], + info = null; + + style.type = 'text/css'; + style.id = 'matchmediajs-test'; + + script && script.parentNode && script.parentNode.insertBefore(style, script); + + // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers + info = 'getComputedStyle' in window && window.getComputedStyle(style, null) || style.currentStyle; + + styleMedia = { + matchMedium: function (media) { + var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }'; + + // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers + if (style.styleSheet) { + style.styleSheet.cssText = text; + } else { + style.textContent = text; + } + + // Test if media query is true or false + return info.width === '1px'; + } + }; + } + + return function (media) { + return { + matches: styleMedia.matchMedium(media || 'all'), + media: media || 'all' + }; + }; + }()); + + // Thank you: https://github.com/sindresorhus/query-string + function parseStyleToObject(str) { + var styleObject = {}; + + if (typeof str !== 'string') { + return styleObject; + } + + str = str.trim().slice(1, -1); // browsers re-quote string style values + + if (!str) { + return styleObject; + } + + styleObject = str.split('&').reduce(function (ret, param) { + var parts = param.replace(/\+/g, ' ').split('='); + var key = parts[0]; + var val = parts[1]; + key = decodeURIComponent(key); + + // missing `=` should be `null`: + // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters + val = val === undefined ? null : decodeURIComponent(val); + + if (!ret.hasOwnProperty(key)) { + ret[key] = val; + } else if (Array.isArray(ret[key])) { + ret[key].push(val); + } else { + ret[key] = [ret[key], val]; + } + return ret; + }, {}); + + return styleObject; + } + + Foundation.MediaQuery = MediaQuery; +}(jQuery); +'use strict'; + +!function ($) { + + /** + * Motion module. + * @module foundation.motion + */ + + var initClasses = ['mui-enter', 'mui-leave']; + var activeClasses = ['mui-enter-active', 'mui-leave-active']; + + var Motion = { + animateIn: function (element, animation, cb) { + animate(true, element, animation, cb); + }, + + animateOut: function (element, animation, cb) { + animate(false, element, animation, cb); + } + }; + + function Move(duration, elem, fn) { + var anim, + prog, + start = null; + // console.log('called'); + + function move(ts) { + if (!start) start = window.performance.now(); + // console.log(start, ts); + prog = ts - start; + fn.apply(elem); + + if (prog < duration) { + anim = window.requestAnimationFrame(move, elem); + } else { + window.cancelAnimationFrame(anim); + elem.trigger('finished.zf.animate', [elem]).triggerHandler('finished.zf.animate', [elem]); + } + } + anim = window.requestAnimationFrame(move); + } + + /** + * Animates an element in or out using a CSS transition class. + * @function + * @private + * @param {Boolean} isIn - Defines if the animation is in or out. + * @param {Object} element - jQuery or HTML object to animate. + * @param {String} animation - CSS class to use. + * @param {Function} cb - Callback to run when animation is finished. + */ + function animate(isIn, element, animation, cb) { + element = $(element).eq(0); + + if (!element.length) return; + + var initClass = isIn ? initClasses[0] : initClasses[1]; + var activeClass = isIn ? activeClasses[0] : activeClasses[1]; + + // Set up the animation + reset(); + + element.addClass(animation).css('transition', 'none'); + + requestAnimationFrame(function () { + element.addClass(initClass); + if (isIn) element.show(); + }); + + // Start the animation + requestAnimationFrame(function () { + element[0].offsetWidth; + element.css('transition', '').addClass(activeClass); + }); + + // Clean up the animation when it finishes + element.one(Foundation.transitionend(element), finish); + + // Hides the element (for out animations), resets the element, and runs a callback + function finish() { + if (!isIn) element.hide(); + reset(); + if (cb) cb.apply(element); + } + + // Resets transitions and removes motion-specific classes + function reset() { + element[0].style.transitionDuration = 0; + element.removeClass(initClass + ' ' + activeClass + ' ' + animation); + } + } + + Foundation.Move = Move; + Foundation.Motion = Motion; +}(jQuery); +'use strict'; + +!function ($) { + + var Nest = { + Feather: function (menu) { + var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'zf'; + + menu.attr('role', 'menubar'); + + var items = menu.find('li').attr({ 'role': 'menuitem' }), + subMenuClass = 'is-' + type + '-submenu', + subItemClass = subMenuClass + '-item', + hasSubClass = 'is-' + type + '-submenu-parent'; + + menu.find('a:first').attr('tabindex', 0); + + items.each(function () { + var $item = $(this), + $sub = $item.children('ul'); + + if ($sub.length) { + $item.addClass(hasSubClass).attr({ + 'aria-haspopup': true, + 'aria-expanded': false, + 'aria-label': $item.children('a:first').text() + }); + + $sub.addClass('submenu ' + subMenuClass).attr({ + 'data-submenu': '', + 'aria-hidden': true, + 'role': 'menu' + }); + } + + if ($item.parent('[data-submenu]').length) { + $item.addClass('is-submenu-item ' + subItemClass); + } + }); + + return; + }, + Burn: function (menu, type) { + var items = menu.find('li').removeAttr('tabindex'), + subMenuClass = 'is-' + type + '-submenu', + subItemClass = subMenuClass + '-item', + hasSubClass = 'is-' + type + '-submenu-parent'; + + menu.find('>li, .menu, .menu > li').removeClass(subMenuClass + ' ' + subItemClass + ' ' + hasSubClass + ' is-submenu-item submenu is-active').removeAttr('data-submenu').css('display', ''); + + // console.log( menu.find('.' + subMenuClass + ', .' + subItemClass + ', .has-submenu, .is-submenu-item, .submenu, [data-submenu]') + // .removeClass(subMenuClass + ' ' + subItemClass + ' has-submenu is-submenu-item submenu') + // .removeAttr('data-submenu')); + // items.each(function(){ + // var $item = $(this), + // $sub = $item.children('ul'); + // if($item.parent('[data-submenu]').length){ + // $item.removeClass('is-submenu-item ' + subItemClass); + // } + // if($sub.length){ + // $item.removeClass('has-submenu'); + // $sub.removeClass('submenu ' + subMenuClass).removeAttr('data-submenu'); + // } + // }); + } + }; + + Foundation.Nest = Nest; +}(jQuery); +'use strict'; + +!function ($) { + + function Timer(elem, options, cb) { + var _this = this, + duration = options.duration, + //options is an object for easily adding features later. + nameSpace = Object.keys(elem.data())[0] || 'timer', + remain = -1, + start, + timer; + + this.isPaused = false; + + this.restart = function () { + remain = -1; + clearTimeout(timer); + this.start(); + }; + + this.start = function () { + this.isPaused = false; + // if(!elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things. + clearTimeout(timer); + remain = remain <= 0 ? duration : remain; + elem.data('paused', false); + start = Date.now(); + timer = setTimeout(function () { + if (options.infinite) { + _this.restart(); //rerun the timer. + } + if (cb && typeof cb === 'function') { + cb(); + } + }, remain); + elem.trigger('timerstart.zf.' + nameSpace); + }; + + this.pause = function () { + this.isPaused = true; + //if(elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things. + clearTimeout(timer); + elem.data('paused', true); + var end = Date.now(); + remain = remain - (end - start); + elem.trigger('timerpaused.zf.' + nameSpace); + }; + } + + /** + * Runs a callback function when images are fully loaded. + * @param {Object} images - Image(s) to check if loaded. + * @param {Func} callback - Function to execute when image is fully loaded. + */ + function onImagesLoaded(images, callback) { + var self = this, + unloaded = images.length; + + if (unloaded === 0) { + callback(); + } + + images.each(function () { + if (this.complete) { + singleImageLoaded(); + } else if (typeof this.naturalWidth !== 'undefined' && this.naturalWidth > 0) { + singleImageLoaded(); + } else { + $(this).one('load', function () { + singleImageLoaded(); + }); + } + }); + + function singleImageLoaded() { + unloaded--; + if (unloaded === 0) { + callback(); + } + } + } + + Foundation.Timer = Timer; + Foundation.onImagesLoaded = onImagesLoaded; +}(jQuery); +//************************************************** +//**Work inspired by multiple jquery swipe plugins** +//**Done by Yohai Ararat *************************** +//************************************************** +(function ($) { + + $.spotSwipe = { + version: '1.0.0', + enabled: 'ontouchstart' in document.documentElement, + preventDefault: false, + moveThreshold: 75, + timeThreshold: 200 + }; + + var startPosX, + startPosY, + startTime, + elapsedTime, + isMoving = false; + + function onTouchEnd() { + // alert(this); + this.removeEventListener('touchmove', onTouchMove); + this.removeEventListener('touchend', onTouchEnd); + isMoving = false; + } + + function onTouchMove(e) { + if ($.spotSwipe.preventDefault) { + e.preventDefault(); + } + if (isMoving) { + var x = e.touches[0].pageX; + var y = e.touches[0].pageY; + var dx = startPosX - x; + var dy = startPosY - y; + var dir; + elapsedTime = new Date().getTime() - startTime; + if (Math.abs(dx) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) { + dir = dx > 0 ? 'left' : 'right'; + } + // else if(Math.abs(dy) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) { + // dir = dy > 0 ? 'down' : 'up'; + // } + if (dir) { + e.preventDefault(); + onTouchEnd.call(this); + $(this).trigger('swipe', dir).trigger('swipe' + dir); + } + } + } + + function onTouchStart(e) { + if (e.touches.length == 1) { + startPosX = e.touches[0].pageX; + startPosY = e.touches[0].pageY; + isMoving = true; + startTime = new Date().getTime(); + this.addEventListener('touchmove', onTouchMove, false); + this.addEventListener('touchend', onTouchEnd, false); + } + } + + function init() { + this.addEventListener && this.addEventListener('touchstart', onTouchStart, false); + } + + function teardown() { + this.removeEventListener('touchstart', onTouchStart); + } + + $.event.special.swipe = { setup: init }; + + $.each(['left', 'up', 'down', 'right'], function () { + $.event.special['swipe' + this] = { setup: function () { + $(this).on('swipe', $.noop); + } }; + }); +})(jQuery); +/**************************************************** + * Method for adding psuedo drag events to elements * + ***************************************************/ +!function ($) { + $.fn.addTouch = function () { + this.each(function (i, el) { + $(el).bind('touchstart touchmove touchend touchcancel', function () { + //we pass the original event object because the jQuery event + //object is normalized to w3c specs and does not provide the TouchList + handleTouch(event); + }); + }); + + var handleTouch = function (event) { + var touches = event.changedTouches, + first = touches[0], + eventTypes = { + touchstart: 'mousedown', + touchmove: 'mousemove', + touchend: 'mouseup' + }, + type = eventTypes[event.type], + simulatedEvent; + + if ('MouseEvent' in window && typeof window.MouseEvent === 'function') { + simulatedEvent = new window.MouseEvent(type, { + 'bubbles': true, + 'cancelable': true, + 'screenX': first.screenX, + 'screenY': first.screenY, + 'clientX': first.clientX, + 'clientY': first.clientY + }); + } else { + simulatedEvent = document.createEvent('MouseEvent'); + simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0 /*left*/, null); + } + first.target.dispatchEvent(simulatedEvent); + }; + }; +}(jQuery); + +//********************************** +//**From the jQuery Mobile Library** +//**need to recreate functionality** +//**and try to improve if possible** +//********************************** + +/* Removing the jQuery function **** +************************************ + +(function( $, window, undefined ) { + + var $document = $( document ), + // supportTouch = $.mobile.support.touch, + touchStartEvent = 'touchstart'//supportTouch ? "touchstart" : "mousedown", + touchStopEvent = 'touchend'//supportTouch ? "touchend" : "mouseup", + touchMoveEvent = 'touchmove'//supportTouch ? "touchmove" : "mousemove"; + + // setup new event shortcuts + $.each( ( "touchstart touchmove touchend " + + "swipe swipeleft swiperight" ).split( " " ), function( i, name ) { + + $.fn[ name ] = function( fn ) { + return fn ? this.bind( name, fn ) : this.trigger( name ); + }; + + // jQuery < 1.8 + if ( $.attrFn ) { + $.attrFn[ name ] = true; + } + }); + + function triggerCustomEvent( obj, eventType, event, bubble ) { + var originalType = event.type; + event.type = eventType; + if ( bubble ) { + $.event.trigger( event, undefined, obj ); + } else { + $.event.dispatch.call( obj, event ); + } + event.type = originalType; + } + + // also handles taphold + + // Also handles swipeleft, swiperight + $.event.special.swipe = { + + // More than this horizontal displacement, and we will suppress scrolling. + scrollSupressionThreshold: 30, + + // More time than this, and it isn't a swipe. + durationThreshold: 1000, + + // Swipe horizontal displacement must be more than this. + horizontalDistanceThreshold: window.devicePixelRatio >= 2 ? 15 : 30, + + // Swipe vertical displacement must be less than this. + verticalDistanceThreshold: window.devicePixelRatio >= 2 ? 15 : 30, + + getLocation: function ( event ) { + var winPageX = window.pageXOffset, + winPageY = window.pageYOffset, + x = event.clientX, + y = event.clientY; + + if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) || + event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) { + + // iOS4 clientX/clientY have the value that should have been + // in pageX/pageY. While pageX/page/ have the value 0 + x = x - winPageX; + y = y - winPageY; + } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) { + + // Some Android browsers have totally bogus values for clientX/Y + // when scrolling/zooming a page. Detectable since clientX/clientY + // should never be smaller than pageX/pageY minus page scroll + x = event.pageX - winPageX; + y = event.pageY - winPageY; + } + + return { + x: x, + y: y + }; + }, + + start: function( event ) { + var data = event.originalEvent.touches ? + event.originalEvent.touches[ 0 ] : event, + location = $.event.special.swipe.getLocation( data ); + return { + time: ( new Date() ).getTime(), + coords: [ location.x, location.y ], + origin: $( event.target ) + }; + }, + + stop: function( event ) { + var data = event.originalEvent.touches ? + event.originalEvent.touches[ 0 ] : event, + location = $.event.special.swipe.getLocation( data ); + return { + time: ( new Date() ).getTime(), + coords: [ location.x, location.y ] + }; + }, + + handleSwipe: function( start, stop, thisObject, origTarget ) { + if ( stop.time - start.time < $.event.special.swipe.durationThreshold && + Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold && + Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) { + var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; + + triggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop }), true ); + triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true ); + return true; + } + return false; + + }, + + // This serves as a flag to ensure that at most one swipe event event is + // in work at any given time + eventInProgress: false, + + setup: function() { + var events, + thisObject = this, + $this = $( thisObject ), + context = {}; + + // Retrieve the events data for this element and add the swipe context + events = $.data( this, "mobile-events" ); + if ( !events ) { + events = { length: 0 }; + $.data( this, "mobile-events", events ); + } + events.length++; + events.swipe = context; + + context.start = function( event ) { + + // Bail if we're already working on a swipe event + if ( $.event.special.swipe.eventInProgress ) { + return; + } + $.event.special.swipe.eventInProgress = true; + + var stop, + start = $.event.special.swipe.start( event ), + origTarget = event.target, + emitted = false; + + context.move = function( event ) { + if ( !start || event.isDefaultPrevented() ) { + return; + } + + stop = $.event.special.swipe.stop( event ); + if ( !emitted ) { + emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget ); + if ( emitted ) { + + // Reset the context to make way for the next swipe event + $.event.special.swipe.eventInProgress = false; + } + } + // prevent scrolling + if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) { + event.preventDefault(); + } + }; + + context.stop = function() { + emitted = true; + + // Reset the context to make way for the next swipe event + $.event.special.swipe.eventInProgress = false; + $document.off( touchMoveEvent, context.move ); + context.move = null; + }; + + $document.on( touchMoveEvent, context.move ) + .one( touchStopEvent, context.stop ); + }; + $this.on( touchStartEvent, context.start ); + }, + + teardown: function() { + var events, context; + + events = $.data( this, "mobile-events" ); + if ( events ) { + context = events.swipe; + delete events.swipe; + events.length--; + if ( events.length === 0 ) { + $.removeData( this, "mobile-events" ); + } + } + + if ( context ) { + if ( context.start ) { + $( this ).off( touchStartEvent, context.start ); + } + if ( context.move ) { + $document.off( touchMoveEvent, context.move ); + } + if ( context.stop ) { + $document.off( touchStopEvent, context.stop ); + } + } + } + }; + $.each({ + swipeleft: "swipe.left", + swiperight: "swipe.right" + }, function( event, sourceEvent ) { + + $.event.special[ event ] = { + setup: function() { + $( this ).bind( sourceEvent, $.noop ); + }, + teardown: function() { + $( this ).unbind( sourceEvent ); + } + }; + }); +})( jQuery, this ); +*/ +'use strict'; + +!function ($) { + + var MutationObserver = function () { + var prefixes = ['WebKit', 'Moz', 'O', 'Ms', '']; + for (var i = 0; i < prefixes.length; i++) { + if (prefixes[i] + 'MutationObserver' in window) { + return window[prefixes[i] + 'MutationObserver']; + } + } + return false; + }(); + + var triggers = function (el, type) { + el.data(type).split(' ').forEach(function (id) { + $('#' + id)[type === 'close' ? 'trigger' : 'triggerHandler'](type + '.zf.trigger', [el]); + }); + }; + // Elements with [data-open] will reveal a plugin that supports it when clicked. + $(document).on('click.zf.trigger', '[data-open]', function () { + triggers($(this), 'open'); + }); + + // Elements with [data-close] will close a plugin that supports it when clicked. + // If used without a value on [data-close], the event will bubble, allowing it to close a parent component. + $(document).on('click.zf.trigger', '[data-close]', function () { + var id = $(this).data('close'); + if (id) { + triggers($(this), 'close'); + } else { + $(this).trigger('close.zf.trigger'); + } + }); + + // Elements with [data-toggle] will toggle a plugin that supports it when clicked. + $(document).on('click.zf.trigger', '[data-toggle]', function () { + triggers($(this), 'toggle'); + }); + + // Elements with [data-closable] will respond to close.zf.trigger events. + $(document).on('close.zf.trigger', '[data-closable]', function (e) { + e.stopPropagation(); + var animation = $(this).data('closable'); + + if (animation !== '') { + Foundation.Motion.animateOut($(this), animation, function () { + $(this).trigger('closed.zf'); + }); + } else { + $(this).fadeOut().trigger('closed.zf'); + } + }); + + $(document).on('focus.zf.trigger blur.zf.trigger', '[data-toggle-focus]', function () { + var id = $(this).data('toggle-focus'); + $('#' + id).triggerHandler('toggle.zf.trigger', [$(this)]); + }); + + /** + * Fires once after all other scripts have loaded + * @function + * @private + */ + $(window).on('load', function () { + checkListeners(); + }); + + function checkListeners() { + eventsListener(); + resizeListener(); + scrollListener(); + closemeListener(); + } + + //******** only fires this function once on load, if there's something to watch ******** + function closemeListener(pluginName) { + var yetiBoxes = $('[data-yeti-box]'), + plugNames = ['dropdown', 'tooltip', 'reveal']; + + if (pluginName) { + if (typeof pluginName === 'string') { + plugNames.push(pluginName); + } else if (typeof pluginName === 'object' && typeof pluginName[0] === 'string') { + plugNames.concat(pluginName); + } else { + console.error('Plugin names must be strings'); + } + } + if (yetiBoxes.length) { + var listeners = plugNames.map(function (name) { + return 'closeme.zf.' + name; + }).join(' '); + + $(window).off(listeners).on(listeners, function (e, pluginId) { + var plugin = e.namespace.split('.')[0]; + var plugins = $('[data-' + plugin + ']').not('[data-yeti-box="' + pluginId + '"]'); + + plugins.each(function () { + var _this = $(this); + + _this.triggerHandler('close.zf.trigger', [_this]); + }); + }); + } + } + + function resizeListener(debounce) { + var timer = void 0, + $nodes = $('[data-resize]'); + if ($nodes.length) { + $(window).off('resize.zf.trigger').on('resize.zf.trigger', function (e) { + if (timer) { + clearTimeout(timer); + } + + timer = setTimeout(function () { + + if (!MutationObserver) { + //fallback for IE 9 + $nodes.each(function () { + $(this).triggerHandler('resizeme.zf.trigger'); + }); + } + //trigger all listening elements and signal a resize event + $nodes.attr('data-events', "resize"); + }, debounce || 10); //default time to emit resize event + }); + } + } + + function scrollListener(debounce) { + var timer = void 0, + $nodes = $('[data-scroll]'); + if ($nodes.length) { + $(window).off('scroll.zf.trigger').on('scroll.zf.trigger', function (e) { + if (timer) { + clearTimeout(timer); + } + + timer = setTimeout(function () { + + if (!MutationObserver) { + //fallback for IE 9 + $nodes.each(function () { + $(this).triggerHandler('scrollme.zf.trigger'); + }); + } + //trigger all listening elements and signal a scroll event + $nodes.attr('data-events', "scroll"); + }, debounce || 10); //default time to emit scroll event + }); + } + } + + function eventsListener() { + if (!MutationObserver) { + return false; + } + var nodes = document.querySelectorAll('[data-resize], [data-scroll], [data-mutate]'); + + //element callback + var listeningElementsMutation = function (mutationRecordsList) { + var $target = $(mutationRecordsList[0].target); + //trigger the event handler for the element depending on type + switch ($target.attr("data-events")) { + + case "resize": + $target.triggerHandler('resizeme.zf.trigger', [$target]); + break; + + case "scroll": + $target.triggerHandler('scrollme.zf.trigger', [$target, window.pageYOffset]); + break; + + // case "mutate" : + // console.log('mutate', $target); + // $target.triggerHandler('mutate.zf.trigger'); + // + // //make sure we don't get stuck in an infinite loop from sloppy codeing + // if ($target.index('[data-mutate]') == $("[data-mutate]").length-1) { + // domMutationObserver(); + // } + // break; + + default: + return false; + //nothing + } + }; + + if (nodes.length) { + //for each element that needs to listen for resizing, scrolling, (or coming soon mutation) add a single observer + for (var i = 0; i <= nodes.length - 1; i++) { + var elementObserver = new MutationObserver(listeningElementsMutation); + elementObserver.observe(nodes[i], { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ["data-events"] }); + } + } + } + + // ------------------------------------ + + // [PH] + // Foundation.CheckWatchers = checkWatchers; + Foundation.IHearYou = checkListeners; + // Foundation.ISeeYou = scrollListener; + // Foundation.IFeelYou = closemeListener; +}(jQuery); + +// function domMutationObserver(debounce) { +// // !!! This is coming soon and needs more work; not active !!! // +// var timer, +// nodes = document.querySelectorAll('[data-mutate]'); +// // +// if (nodes.length) { +// // var MutationObserver = (function () { +// // var prefixes = ['WebKit', 'Moz', 'O', 'Ms', '']; +// // for (var i=0; i < prefixes.length; i++) { +// // if (prefixes[i] + 'MutationObserver' in window) { +// // return window[prefixes[i] + 'MutationObserver']; +// // } +// // } +// // return false; +// // }()); +// +// +// //for the body, we need to listen for all changes effecting the style and class attributes +// var bodyObserver = new MutationObserver(bodyMutation); +// bodyObserver.observe(document.body, { attributes: true, childList: true, characterData: false, subtree:true, attributeFilter:["style", "class"]}); +// +// +// //body callback +// function bodyMutation(mutate) { +// //trigger all listening elements and signal a mutation event +// if (timer) { clearTimeout(timer); } +// +// timer = setTimeout(function() { +// bodyObserver.disconnect(); +// $('[data-mutate]').attr('data-events',"mutate"); +// }, debounce || 150); +// } +// } +// } +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +!function ($) { + + /** + * Abide module. + * @module foundation.abide + */ + + var Abide = function () { + /** + * Creates a new instance of Abide. + * @class + * @fires Abide#init + * @param {Object} element - jQuery object to add the trigger to. + * @param {Object} options - Overrides to the default plugin settings. + */ + function Abide(element) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, Abide); + + this.$element = element; + this.options = $.extend({}, Abide.defaults, this.$element.data(), options); + + this._init(); + + Foundation.registerPlugin(this, 'Abide'); + } + + /** + * Initializes the Abide plugin and calls functions to get Abide functioning on load. + * @private + */ + + + _createClass(Abide, [{ + key: '_init', + value: function _init() { + this.$inputs = this.$element.find('input, textarea, select'); + + this._events(); + } + + /** + * Initializes events for Abide. + * @private + */ + + }, { + key: '_events', + value: function _events() { + var _this2 = this; + + this.$element.off('.abide').on('reset.zf.abide', function () { + _this2.resetForm(); + }).on('submit.zf.abide', function () { + return _this2.validateForm(); + }); + + if (this.options.validateOn === 'fieldChange') { + this.$inputs.off('change.zf.abide').on('change.zf.abide', function (e) { + _this2.validateInput($(e.target)); + }); + } + + if (this.options.liveValidate) { + this.$inputs.off('input.zf.abide').on('input.zf.abide', function (e) { + _this2.validateInput($(e.target)); + }); + } + } + + /** + * Calls necessary functions to update Abide upon DOM change + * @private + */ + + }, { + key: '_reflow', + value: function _reflow() { + this._init(); + } + + /** + * Checks whether or not a form element has the required attribute and if it's checked or not + * @param {Object} element - jQuery object to check for required attribute + * @returns {Boolean} Boolean value depends on whether or not attribute is checked or empty + */ + + }, { + key: 'requiredCheck', + value: function requiredCheck($el) { + if (!$el.attr('required')) return true; + + var isGood = true; + + switch ($el[0].type) { + case 'checkbox': + isGood = $el[0].checked; + break; + + case 'select': + case 'select-one': + case 'select-multiple': + var opt = $el.find('option:selected'); + if (!opt.length || !opt.val()) isGood = false; + break; + + default: + if (!$el.val() || !$el.val().length) isGood = false; + } + + return isGood; + } + + /** + * Based on $el, get the first element with selector in this order: + * 1. The element's direct sibling('s). + * 3. The element's parent's children. + * + * This allows for multiple form errors per input, though if none are found, no form errors will be shown. + * + * @param {Object} $el - jQuery object to use as reference to find the form error selector. + * @returns {Object} jQuery object with the selector. + */ + + }, { + key: 'findFormError', + value: function findFormError($el) { + var $error = $el.siblings(this.options.formErrorSelector); + + if (!$error.length) { + $error = $el.parent().find(this.options.formErrorSelector); + } + + return $error; + } + + /** + * Get the first element in this order: + * 2. The